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.

2746 lines
79 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: ssl3msg.c
  7. //
  8. // Contents: Main crypto functions for SSL3.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 04-16-96 ramas Created.
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. //------------------------------------------------------------------------------------------
  19. SP_STATUS WINAPI
  20. Ssl3DecryptHandler(
  21. PSPContext pContext,
  22. PSPBuffer pCommInput,
  23. PSPBuffer pAppOutput)
  24. {
  25. SP_STATUS pctRet = PCT_ERR_OK;
  26. if(pCommInput->cbData == 0)
  27. {
  28. return PCT_INT_INCOMPLETE_MSG;
  29. }
  30. if(!(pContext->State & SP_STATE_CONNECTED) || pContext->Decrypt == NULL)
  31. {
  32. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  33. }
  34. switch(*(PBYTE)pCommInput->pvBuffer)
  35. {
  36. case SSL3_CT_HANDSHAKE:
  37. if(pContext->RipeZombie->fProtocol & SP_PROT_CLIENTS)
  38. {
  39. // This should be either a HelloRequest message, which means that
  40. // the server is requesting a renegotiation, or a ServerHello
  41. // message, which means that the server is responding to a
  42. // renegotiation request that we made.
  43. // The first thing we need to do is to figure out which it is.
  44. // We want to go ahead and decrypt the HelloRequest message, but
  45. // if it's a server hello message we want to punt this back to the
  46. // application so that they can give it to the LSA process via
  47. // a call to InitializeSecurityContext.
  48. // BUGBUG - We should change the context state when we request
  49. // renegotiation and then just check the state here, but that's
  50. // hard to do so for now we'll just check the size of the packet.
  51. if(pCommInput->cbBuffer > sizeof(SWRAP) +
  52. sizeof(SHSH) +
  53. pContext->pCipherInfo->dwBlockSize +
  54. pContext->pHashInfo->cbCheckSum)
  55. {
  56. // Must be a ServerHello message.
  57. pCommInput->cbData = 0;
  58. pContext->State = SSL3_STATE_CLIENT_HELLO;
  59. }
  60. else
  61. {
  62. // This should be a HelloRequest message. We should make sure, and
  63. // then completely consume the message.
  64. pctRet = pContext->Decrypt( pContext,
  65. pCommInput, // message
  66. pAppOutput); // Unpacked Message
  67. if(PCT_ERR_OK != pctRet)
  68. {
  69. return pctRet;
  70. }
  71. if(*(PBYTE)pAppOutput->pvBuffer != SSL3_HS_HELLO_REQUEST ||
  72. pAppOutput->cbData != sizeof(SHSH))
  73. {
  74. // This ain't no HelloRequest!
  75. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  76. }
  77. pContext->State = SSL3_STATE_GEN_HELLO_REQUEST;
  78. }
  79. }
  80. else
  81. {
  82. // This is probably a ClientHello message. In any case, let the
  83. // caller deal with it (by passing it to the LSA process).
  84. pCommInput->cbData = 0;
  85. pContext->State = SSL3_STATE_RENEGOTIATE;
  86. }
  87. pAppOutput->cbData = 0;
  88. return SP_LOG_RESULT(PCT_INT_RENEGOTIATE);
  89. case SSL3_CT_ALERT:
  90. pctRet = pContext->Decrypt( pContext,
  91. pCommInput,
  92. pAppOutput);
  93. if(PCT_ERR_OK != pctRet)
  94. {
  95. return pctRet;
  96. }
  97. pctRet = ParseAlertMessage(pContext,
  98. (PBYTE)pAppOutput->pvBuffer,
  99. pAppOutput->cbData);
  100. // make sure that APP doesn't see Alert messages...
  101. pAppOutput->cbData = 0;
  102. return pctRet;
  103. case SSL3_CT_APPLICATIONDATA:
  104. pctRet = pContext->Decrypt( pContext,
  105. pCommInput,
  106. pAppOutput);
  107. return pctRet;
  108. default:
  109. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  110. }
  111. }
  112. SP_STATUS WINAPI
  113. Ssl3GetHeaderSize(
  114. PSPContext pContext,
  115. PSPBuffer pCommInput,
  116. DWORD * pcbHeaderSize)
  117. {
  118. UNREFERENCED_PARAMETER(pContext);
  119. UNREFERENCED_PARAMETER(pCommInput);
  120. if(pcbHeaderSize == NULL)
  121. {
  122. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  123. }
  124. *pcbHeaderSize = sizeof(SWRAP);
  125. return PCT_ERR_OK;
  126. }
  127. #if VERIFYHASH
  128. BYTE rgb3Mac[2048];
  129. DWORD ibMac = 0;
  130. #endif
  131. //+---------------------------------------------------------------------------
  132. //
  133. // Function: Ssl3ComputeMac
  134. //
  135. // Synopsis:
  136. //
  137. // Arguments: [pContext] --
  138. // [fReadMac] --
  139. // [pClean] --
  140. // [cContentType] --
  141. // [pbMac] --
  142. // [cbMac]
  143. //
  144. // History: 10-03-97 jbanes Created.
  145. //
  146. // Notes:
  147. //
  148. //----------------------------------------------------------------------------
  149. SP_STATUS
  150. Ssl3ComputeMac(
  151. PSPContext pContext,
  152. BOOL fReadMac,
  153. PSPBuffer pClean,
  154. CHAR cContentType,
  155. PBYTE pbMac,
  156. DWORD cbMac)
  157. {
  158. HCRYPTHASH hHash = 0;
  159. DWORD dwReverseSequence;
  160. WORD wReverseData;
  161. UCHAR rgbDigest[SP_MAX_DIGEST_LEN];
  162. DWORD cbDigest;
  163. BYTE rgbPad[CB_SSL3_MAX_MAC_PAD];
  164. WORD cbPad;
  165. HCRYPTPROV hProv;
  166. HCRYPTKEY hSecret;
  167. DWORD dwSequence;
  168. PHashInfo pHashInfo;
  169. SP_STATUS pctRet;
  170. UNREFERENCED_PARAMETER(cbMac);
  171. if(fReadMac)
  172. {
  173. hProv = pContext->hReadProv;
  174. hSecret = pContext->hReadMAC;
  175. dwSequence = pContext->ReadCounter;
  176. pHashInfo = pContext->pReadHashInfo;
  177. }
  178. else
  179. {
  180. hProv = pContext->hWriteProv;
  181. hSecret = pContext->hWriteMAC;
  182. dwSequence = pContext->WriteCounter;
  183. pHashInfo = pContext->pWriteHashInfo;
  184. }
  185. if(!hProv)
  186. {
  187. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  188. }
  189. // Determine size of pad_1 and pad_2.
  190. if(pHashInfo->aiHash == CALG_MD5)
  191. {
  192. cbPad = CB_SSL3_MD5_MAC_PAD;
  193. }
  194. else
  195. {
  196. cbPad = CB_SSL3_SHA_MAC_PAD;
  197. }
  198. //
  199. // hash(MAC_write_secret + pad_2 +
  200. // hash(MAC_write_secret + pad_1 + seq_num +
  201. // SSLCompressed.type + SSLCompressed.length +
  202. // SSLCompressed.fragment));
  203. //
  204. // Create hash
  205. if(!CryptCreateHash(hProv,
  206. pHashInfo->aiHash,
  207. 0,
  208. 0,
  209. &hHash))
  210. {
  211. SP_LOG_RESULT(GetLastError());
  212. pctRet = PCT_INT_INTERNAL_ERROR;
  213. goto cleanup;
  214. }
  215. // Hash secret
  216. if(!CryptHashSessionKey(hHash,
  217. hSecret,
  218. CRYPT_LITTLE_ENDIAN))
  219. {
  220. SP_LOG_RESULT(GetLastError());
  221. pctRet = PCT_INT_INTERNAL_ERROR;
  222. goto cleanup;
  223. }
  224. // hash pad 1
  225. FillMemory(rgbPad, cbPad, PAD1_CONSTANT);
  226. if(!CryptHashData(hHash, rgbPad, cbPad, 0))
  227. {
  228. SP_LOG_RESULT(GetLastError());
  229. pctRet = PCT_INT_INTERNAL_ERROR;
  230. goto cleanup;
  231. }
  232. /* add count */
  233. dwReverseSequence = 0;
  234. if(!CryptHashData(hHash,
  235. (PUCHAR)&dwReverseSequence,
  236. sizeof(DWORD),
  237. 0))
  238. {
  239. SP_LOG_RESULT(GetLastError());
  240. pctRet = PCT_INT_INTERNAL_ERROR;
  241. goto cleanup;
  242. }
  243. dwReverseSequence = htonl(dwSequence);
  244. if(!CryptHashData(hHash,
  245. (PUCHAR)&dwReverseSequence,
  246. sizeof(DWORD),
  247. 0))
  248. {
  249. SP_LOG_RESULT(GetLastError());
  250. pctRet = PCT_INT_INTERNAL_ERROR;
  251. goto cleanup;
  252. }
  253. // Add content type.
  254. if(cContentType != 0)
  255. {
  256. if(!CryptHashData(hHash, (PBYTE)&cContentType, 1, 0))
  257. {
  258. SP_LOG_RESULT(GetLastError());
  259. pctRet = PCT_INT_INTERNAL_ERROR;
  260. goto cleanup;
  261. }
  262. }
  263. /* add length */
  264. wReverseData = (WORD)pClean->cbData >> 8 | (WORD)pClean->cbData << 8;
  265. if(!CryptHashData(hHash,
  266. (PBYTE)&wReverseData,
  267. sizeof(WORD),
  268. 0))
  269. {
  270. SP_LOG_RESULT(GetLastError());
  271. pctRet = PCT_INT_INTERNAL_ERROR;
  272. goto cleanup;
  273. }
  274. /* add data */
  275. if(!CryptHashData(hHash,
  276. pClean->pvBuffer,
  277. pClean->cbData,
  278. 0))
  279. {
  280. SP_LOG_RESULT(GetLastError());
  281. pctRet = PCT_INT_INTERNAL_ERROR;
  282. goto cleanup;
  283. }
  284. #if VERIFYHASH
  285. if(ibMac > 1800) ibMac = 0;
  286. CopyMemory(&rgb3Mac[ibMac], (BYTE *)&dw32High, sizeof(DWORD));
  287. ibMac += sizeof(DWORD);
  288. CopyMemory(&rgb3Mac[ibMac], (BYTE *)&dwReverseSeq, sizeof(DWORD));
  289. ibMac += sizeof(DWORD);
  290. CopyMemory(&rgb3Mac[ibMac], (BYTE *)&wDataReverse, sizeof(WORD));
  291. ibMac += sizeof(WORD);
  292. if(wData < 50)
  293. {
  294. CopyMemory(&rgb3Mac[ibMac], (PUCHAR)pClean->pvBuffer, wData);
  295. ibMac += wData;
  296. }
  297. #endif
  298. // Get inner hash value.
  299. cbDigest = sizeof(rgbDigest);
  300. if(!CryptGetHashParam(hHash,
  301. HP_HASHVAL,
  302. rgbDigest,
  303. &cbDigest,
  304. 0))
  305. {
  306. SP_LOG_RESULT(GetLastError());
  307. pctRet = PCT_INT_INTERNAL_ERROR;
  308. goto cleanup;
  309. }
  310. SP_ASSERT(pHashInfo->cbCheckSum == cbDigest);
  311. CryptDestroyHash(hHash);
  312. hHash = 0;
  313. #if VERIFYHASH
  314. CopyMemory(&rgb3Mac[ibMac], rgbDigest, pHashInfo->cbCheckSum);
  315. ibMac += pHashInfo->cbCheckSum;
  316. #endif
  317. // Create hash
  318. if(!CryptCreateHash(hProv,
  319. pHashInfo->aiHash,
  320. 0,
  321. 0,
  322. &hHash))
  323. {
  324. SP_LOG_RESULT(GetLastError());
  325. pctRet = PCT_INT_INTERNAL_ERROR;
  326. goto cleanup;
  327. }
  328. // Hash secret
  329. if(!CryptHashSessionKey(hHash,
  330. hSecret,
  331. CRYPT_LITTLE_ENDIAN))
  332. {
  333. SP_LOG_RESULT(GetLastError());
  334. pctRet = PCT_INT_INTERNAL_ERROR;
  335. goto cleanup;
  336. }
  337. // hash pad 2
  338. FillMemory(rgbPad, cbPad, PAD2_CONSTANT);
  339. if(!CryptHashData(hHash, rgbPad, cbPad, 0))
  340. {
  341. SP_LOG_RESULT(GetLastError());
  342. pctRet = PCT_INT_INTERNAL_ERROR;
  343. goto cleanup;
  344. }
  345. if(!CryptHashData(hHash, rgbDigest, cbDigest, 0))
  346. {
  347. SP_LOG_RESULT(GetLastError());
  348. pctRet = PCT_INT_INTERNAL_ERROR;
  349. goto cleanup;
  350. }
  351. // Get outer hash value.
  352. cbDigest = sizeof(rgbDigest);
  353. if(!CryptGetHashParam(hHash,
  354. HP_HASHVAL,
  355. rgbDigest,
  356. &cbDigest,
  357. 0))
  358. {
  359. SP_LOG_RESULT(GetLastError());
  360. pctRet = PCT_INT_INTERNAL_ERROR;
  361. goto cleanup;
  362. }
  363. SP_ASSERT(pHashInfo->cbCheckSum == cbDigest);
  364. CryptDestroyHash(hHash);
  365. hHash = 0;
  366. #if VERIFYHASH
  367. CopyMemory(&rgb3Mac[ibMac], rgbDigest, pHashInfo->cbCheckSum);
  368. ibMac += pHashInfo->cbCheckSum;
  369. #endif
  370. CopyMemory(pbMac, rgbDigest, cbDigest);
  371. pctRet = PCT_ERR_OK;
  372. cleanup:
  373. if(hHash)
  374. {
  375. CryptDestroyHash(hHash);
  376. }
  377. return pctRet;
  378. }
  379. //+---------------------------------------------------------------------------
  380. //
  381. // Function: Ssl3BuildFinishMessage
  382. //
  383. // Synopsis:
  384. //
  385. // Arguments: [pContext] --
  386. // [pbMd5Digest] --
  387. // [pbSHADigest] --
  388. // [fClient] --
  389. //
  390. // History: 10-03-97 jbanes Added server-side CAPI integration.
  391. //
  392. // Notes:
  393. //
  394. //----------------------------------------------------------------------------
  395. SP_STATUS
  396. Ssl3BuildFinishMessage(
  397. PSPContext pContext,
  398. BYTE *pbMd5Digest,
  399. BYTE *pbSHADigest,
  400. BOOL fClient)
  401. {
  402. BYTE rgbPad1[CB_SSL3_MAX_MAC_PAD];
  403. BYTE rgbPad2[CB_SSL3_MAX_MAC_PAD];
  404. BYTE szClnt[] = "CLNT";
  405. BYTE szSrvr[] = "SRVR";
  406. HCRYPTHASH hHash = 0;
  407. DWORD cbDigest;
  408. SP_STATUS pctRet;
  409. //
  410. // Compute the two hash values as follows:
  411. //
  412. // enum { client(0x434c4e54), server(0x53525652) } Sender;
  413. // enum { client("CLNT"), server("SRVR") } Sender;
  414. //
  415. // struct {
  416. // opaque md5_hash[16];
  417. // opaque sha_hash[20];
  418. // } Finished;
  419. //
  420. // md5_hash - MD5(master_secret + pad2 + MD5(handshake_messages +
  421. // Sender + master_secret + pad1))
  422. //
  423. // sha_hash - SHA(master_secret + pad2 + SHA(handshake_messages +
  424. // Sender + master_secret + pad1))
  425. //
  426. // pad_1 - The character 0x36 repeated 48 times for MD5 or
  427. // 40 times for SHA.
  428. //
  429. // pad_2 - The character 0x5c repeated the same number of times.
  430. //
  431. FillMemory(rgbPad1, sizeof(rgbPad1), PAD1_CONSTANT);
  432. FillMemory(rgbPad2, sizeof(rgbPad2), PAD2_CONSTANT);
  433. // Make local copy of the handshake_messages MD5 hash object
  434. if(!CryptDuplicateHash(pContext->hMd5Handshake,
  435. NULL,
  436. 0,
  437. &hHash))
  438. {
  439. SP_LOG_RESULT(GetLastError());
  440. pctRet = PCT_INT_INTERNAL_ERROR;
  441. goto cleanup;
  442. }
  443. // Add rest of stuff to local MD5 hash object.
  444. if(!CryptHashData(hHash,
  445. fClient ? szClnt : szSrvr,
  446. 4,
  447. 0))
  448. {
  449. SP_LOG_RESULT(GetLastError());
  450. pctRet = PCT_INT_INTERNAL_ERROR;
  451. goto cleanup;
  452. }
  453. if(!CryptHashSessionKey(hHash,
  454. pContext->RipeZombie->hMasterKey,
  455. CRYPT_LITTLE_ENDIAN))
  456. {
  457. SP_LOG_RESULT(GetLastError());
  458. pctRet = PCT_INT_INTERNAL_ERROR;
  459. goto cleanup;
  460. }
  461. if(!CryptHashData(hHash,
  462. rgbPad1,
  463. CB_SSL3_MD5_MAC_PAD,
  464. 0))
  465. {
  466. SP_LOG_RESULT(GetLastError());
  467. pctRet = PCT_INT_INTERNAL_ERROR;
  468. goto cleanup;
  469. }
  470. cbDigest = CB_MD5_DIGEST_LEN;
  471. if(!CryptGetHashParam(hHash,
  472. HP_HASHVAL,
  473. pbMd5Digest,
  474. &cbDigest,
  475. 0))
  476. {
  477. SP_LOG_RESULT(GetLastError());
  478. pctRet = PCT_INT_INTERNAL_ERROR;
  479. goto cleanup;
  480. }
  481. CryptDestroyHash(hHash);
  482. hHash = 0;
  483. // Compute "parent" MD5 hash
  484. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  485. CALG_MD5,
  486. 0,
  487. 0,
  488. &hHash))
  489. {
  490. SP_LOG_RESULT(GetLastError());
  491. pctRet = PCT_INT_INTERNAL_ERROR;
  492. goto cleanup;
  493. }
  494. if(!CryptHashSessionKey(hHash,
  495. pContext->RipeZombie->hMasterKey,
  496. CRYPT_LITTLE_ENDIAN))
  497. {
  498. SP_LOG_RESULT(GetLastError());
  499. pctRet = PCT_INT_INTERNAL_ERROR;
  500. goto cleanup;
  501. }
  502. if(!CryptHashData(hHash,
  503. rgbPad2,
  504. CB_SSL3_MD5_MAC_PAD,
  505. 0))
  506. {
  507. SP_LOG_RESULT(GetLastError());
  508. pctRet = PCT_INT_INTERNAL_ERROR;
  509. goto cleanup;
  510. }
  511. if(!CryptHashData(hHash,
  512. pbMd5Digest,
  513. CB_MD5_DIGEST_LEN,
  514. 0))
  515. {
  516. SP_LOG_RESULT(GetLastError());
  517. pctRet = PCT_INT_INTERNAL_ERROR;
  518. goto cleanup;
  519. }
  520. cbDigest = CB_MD5_DIGEST_LEN;
  521. if(!CryptGetHashParam(hHash,
  522. HP_HASHVAL,
  523. pbMd5Digest,
  524. &cbDigest,
  525. 0))
  526. {
  527. SP_LOG_RESULT(GetLastError());
  528. pctRet = PCT_INT_INTERNAL_ERROR;
  529. goto cleanup;
  530. }
  531. CryptDestroyHash(hHash);
  532. hHash = 0;
  533. // Build SHA Hash
  534. // Make local copy of the handshake_messages SHA hash object
  535. if(!CryptDuplicateHash(pContext->hShaHandshake,
  536. NULL,
  537. 0,
  538. &hHash))
  539. {
  540. SP_LOG_RESULT(GetLastError());
  541. pctRet = PCT_INT_INTERNAL_ERROR;
  542. goto cleanup;
  543. }
  544. // SHA(handshake_messages + Sender + master_secret + pad1)
  545. if(!CryptHashData(hHash,
  546. fClient ? szClnt : szSrvr,
  547. 4,
  548. 0))
  549. {
  550. SP_LOG_RESULT(GetLastError());
  551. pctRet = PCT_INT_INTERNAL_ERROR;
  552. goto cleanup;
  553. }
  554. if(!CryptHashSessionKey(hHash,
  555. pContext->RipeZombie->hMasterKey,
  556. CRYPT_LITTLE_ENDIAN))
  557. {
  558. SP_LOG_RESULT(GetLastError());
  559. pctRet = PCT_INT_INTERNAL_ERROR;
  560. goto cleanup;
  561. }
  562. if(!CryptHashData(hHash,
  563. rgbPad1,
  564. CB_SSL3_SHA_MAC_PAD,
  565. 0))
  566. {
  567. SP_LOG_RESULT(GetLastError());
  568. pctRet = PCT_INT_INTERNAL_ERROR;
  569. goto cleanup;
  570. }
  571. cbDigest = A_SHA_DIGEST_LEN;
  572. if(!CryptGetHashParam(hHash,
  573. HP_HASHVAL,
  574. pbSHADigest,
  575. &cbDigest,
  576. 0))
  577. {
  578. SP_LOG_RESULT(GetLastError());
  579. pctRet = PCT_INT_INTERNAL_ERROR;
  580. goto cleanup;
  581. }
  582. CryptDestroyHash(hHash);
  583. hHash = 0;
  584. // SHA(master_secret + pad2 + SHA-hash);
  585. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  586. CALG_SHA,
  587. 0,
  588. 0,
  589. &hHash))
  590. {
  591. SP_LOG_RESULT(GetLastError());
  592. pctRet = PCT_INT_INTERNAL_ERROR;
  593. goto cleanup;
  594. }
  595. if(!CryptHashSessionKey(hHash,
  596. pContext->RipeZombie->hMasterKey,
  597. CRYPT_LITTLE_ENDIAN))
  598. {
  599. SP_LOG_RESULT(GetLastError());
  600. pctRet = PCT_INT_INTERNAL_ERROR;
  601. goto cleanup;
  602. }
  603. if(!CryptHashData(hHash,
  604. rgbPad2,
  605. CB_SSL3_SHA_MAC_PAD,
  606. 0))
  607. {
  608. SP_LOG_RESULT(GetLastError());
  609. pctRet = PCT_INT_INTERNAL_ERROR;
  610. goto cleanup;
  611. }
  612. if(!CryptHashData(hHash,
  613. pbSHADigest,
  614. A_SHA_DIGEST_LEN,
  615. 0))
  616. {
  617. SP_LOG_RESULT(GetLastError());
  618. pctRet = PCT_INT_INTERNAL_ERROR;
  619. goto cleanup;
  620. }
  621. cbDigest = A_SHA_DIGEST_LEN;
  622. if(!CryptGetHashParam(hHash,
  623. HP_HASHVAL,
  624. pbSHADigest,
  625. &cbDigest,
  626. 0))
  627. {
  628. SP_LOG_RESULT(GetLastError());
  629. pctRet = PCT_INT_INTERNAL_ERROR;
  630. goto cleanup;
  631. }
  632. CryptDestroyHash(hHash);
  633. hHash = 0;
  634. pctRet = PCT_ERR_OK;
  635. cleanup:
  636. if(hHash)
  637. {
  638. CryptDestroyHash(hHash);
  639. }
  640. return pctRet;
  641. }
  642. /*****************************************************************************/
  643. DWORD Ssl3CiphertextLen(
  644. PSPContext pContext,
  645. DWORD cbMessage,
  646. BOOL fClientIsSender)
  647. {
  648. DWORD cbBlock;
  649. UNREFERENCED_PARAMETER(fClientIsSender);
  650. // Abort early if we're not encrypting.
  651. if(pContext->pWriteCipherInfo == NULL)
  652. {
  653. // Add record header length.
  654. cbMessage += sizeof(SWRAP);
  655. return cbMessage;
  656. }
  657. // Add MAC length.
  658. cbMessage += pContext->pWriteHashInfo->cbCheckSum;
  659. // Add padding if we're using a block cipher.
  660. cbBlock = pContext->pWriteCipherInfo->dwBlockSize;
  661. if(cbBlock > 1)
  662. {
  663. cbMessage += cbBlock - cbMessage % cbBlock;
  664. }
  665. // Add record header length.
  666. cbMessage += sizeof(SWRAP);
  667. return cbMessage;
  668. }
  669. //+---------------------------------------------------------------------------
  670. //
  671. // Function: Ssl3EncryptRaw
  672. //
  673. // Synopsis: Perform the MAC and encryption steps on an SSL3 record.
  674. //
  675. // Arguments: [pContext] -- Schannel context.
  676. // [pAppInput] -- Data to be encrypted.
  677. // [pCommOutput] -- (output) Encrypted SSL3 record.
  678. // [bContentType] -- SSL3 context type.
  679. //
  680. // History: 10-22-97 jbanes CAPI integrated.
  681. //
  682. // Notes: This function doesn't touch the header portion of the SSL3
  683. // record. This is handle by the calling function.
  684. //
  685. //----------------------------------------------------------------------------
  686. SP_STATUS WINAPI
  687. Ssl3EncryptRaw(
  688. PSPContext pContext,
  689. PSPBuffer pAppInput,
  690. PSPBuffer pCommOutput,
  691. BYTE bContentType)
  692. {
  693. SP_STATUS pctRet;
  694. SPBuffer Clean;
  695. SPBuffer Encrypted;
  696. DWORD cbBlock;
  697. DWORD cbPadding;
  698. PUCHAR pbMAC = NULL;
  699. BOOL fIsClient = FALSE;
  700. DWORD cbBuffExpected;
  701. if((pContext == NULL) ||
  702. (pContext->RipeZombie == NULL) ||
  703. (pContext->pWriteHashInfo == NULL) ||
  704. (pContext->pWriteCipherInfo == NULL) ||
  705. (pAppInput == NULL) ||
  706. (pCommOutput == NULL) ||
  707. (pAppInput->pvBuffer == NULL) ||
  708. (pCommOutput->pvBuffer == NULL))
  709. {
  710. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  711. }
  712. if(pAppInput->cbData > pAppInput->cbBuffer)
  713. {
  714. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  715. }
  716. fIsClient = ( 0 != (pContext->RipeZombie->fProtocol & SP_PROT_SSL3TLS1_CLIENTS));
  717. cbBuffExpected = Ssl3CiphertextLen(pContext, pAppInput->cbData, fIsClient);
  718. if(cbBuffExpected == 0)
  719. {
  720. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  721. }
  722. if(pCommOutput->cbBuffer < cbBuffExpected)
  723. {
  724. return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  725. }
  726. Clean.cbData = pAppInput->cbData;
  727. Clean.pvBuffer = (PUCHAR)pCommOutput->pvBuffer + sizeof(SWRAP);
  728. Clean.cbBuffer = pCommOutput->cbBuffer - sizeof(SWRAP);
  729. /* Move data out of the way if necessary */
  730. if(Clean.pvBuffer != pAppInput->pvBuffer)
  731. {
  732. DebugLog((DEB_WARN, "SSL3EncryptRaw: Unnecessary Move, performance hog\n"));
  733. MoveMemory(Clean.pvBuffer,
  734. pAppInput->pvBuffer,
  735. pAppInput->cbData);
  736. }
  737. // Transfer the write key over from the application process.
  738. if(pContext->hWriteKey == 0 &&
  739. pContext->pWriteCipherInfo->aiCipher != CALG_NULLCIPHER)
  740. {
  741. DebugLog((DEB_TRACE, "Transfer write key from user process.\n"));
  742. pctRet = SPGetUserKeys(pContext, SCH_FLAG_WRITE_KEY);
  743. if(pctRet != PCT_ERR_OK)
  744. {
  745. return SP_LOG_RESULT(pctRet);
  746. }
  747. }
  748. // Compute MAC and add it to end of message.
  749. pbMAC = (PUCHAR)Clean.pvBuffer + Clean.cbData;
  750. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  751. {
  752. pctRet = Ssl3ComputeMac(pContext,
  753. FALSE,
  754. &Clean,
  755. bContentType,
  756. pbMAC,
  757. pContext->pWriteHashInfo->cbCheckSum);
  758. if(pctRet != PCT_ERR_OK)
  759. {
  760. return pctRet;
  761. }
  762. }
  763. else
  764. {
  765. pctRet = Tls1ComputeMac(pContext,
  766. FALSE,
  767. &Clean,
  768. bContentType,
  769. pbMAC,
  770. pContext->pWriteHashInfo->cbCheckSum);
  771. if(pctRet != PCT_ERR_OK)
  772. {
  773. return pctRet;
  774. }
  775. }
  776. Clean.cbData += pContext->pWriteHashInfo->cbCheckSum;
  777. pContext->WriteCounter++;
  778. // Add block cipher padding to end of message.
  779. cbBlock = pContext->pWriteCipherInfo->dwBlockSize;
  780. if(cbBlock > 1)
  781. {
  782. // This is a block cipher.
  783. cbPadding = cbBlock - Clean.cbData % cbBlock;
  784. FillMemory((PUCHAR)Clean.pvBuffer + Clean.cbData,
  785. cbPadding,
  786. (UCHAR)(cbPadding - 1));
  787. Clean.cbData += cbPadding;
  788. }
  789. SP_ASSERT(Clean.cbData <= Clean.cbBuffer);
  790. Encrypted.cbData = Clean.cbData;
  791. Encrypted.pvBuffer = Clean.pvBuffer;
  792. Encrypted.cbBuffer = Clean.cbBuffer;
  793. // Encrypt message.
  794. if(pContext->pWriteCipherInfo->aiCipher != CALG_NULLCIPHER)
  795. {
  796. if(!CryptEncrypt(pContext->hWriteKey,
  797. 0, FALSE, 0,
  798. Encrypted.pvBuffer,
  799. &Encrypted.cbData,
  800. Encrypted.cbBuffer))
  801. {
  802. SP_LOG_RESULT(GetLastError());
  803. return PCT_INT_INTERNAL_ERROR;
  804. }
  805. }
  806. pCommOutput->cbData = Encrypted.cbData + sizeof(SWRAP);
  807. return PCT_ERR_OK;
  808. }
  809. //+---------------------------------------------------------------------------
  810. //
  811. // Function: Ssl3EncryptMessage
  812. //
  813. // Synopsis: Encode a block of data as an SSL3 record.
  814. //
  815. // Arguments: [pContext] -- Schannel context.
  816. // [pAppInput] -- Data to be encrypted.
  817. // [pCommOutput] -- (output) Completed SSL3 record.
  818. //
  819. // History: 10-22-97 jbanes CAPI integrated.
  820. //
  821. // Notes: An SSL3 record is formatted as:
  822. //
  823. // BYTE header[5];
  824. // BYTE data[pAppInput->cbData];
  825. // BYTE mac[mac_size];
  826. // BYTE padding[padding_size];
  827. //
  828. //----------------------------------------------------------------------------
  829. SP_STATUS WINAPI
  830. Ssl3EncryptMessage( PSPContext pContext,
  831. PSPBuffer pAppInput,
  832. PSPBuffer pCommOutput)
  833. {
  834. DWORD cbMessage;
  835. SP_STATUS pctRet;
  836. SP_BEGIN("Ssl3EncryptMessage");
  837. if((pContext == NULL) ||
  838. (pContext->RipeZombie == NULL) ||
  839. (pAppInput == NULL) ||
  840. (pCommOutput == NULL) ||
  841. (pCommOutput->pvBuffer == NULL))
  842. {
  843. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  844. }
  845. DebugLog((DEB_TRACE, "Input: cbData:0x%x, cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  846. pAppInput->cbData,
  847. pAppInput->cbBuffer,
  848. pAppInput->pvBuffer));
  849. DebugLog((DEB_TRACE, "Output: cbData:0x%x, cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  850. pCommOutput->cbData,
  851. pCommOutput->cbBuffer,
  852. pCommOutput->pvBuffer));
  853. // Compute encrypted message size.
  854. cbMessage = Ssl3CiphertextLen(pContext, pAppInput->cbData, TRUE);
  855. pctRet = Ssl3EncryptRaw(pContext, pAppInput, pCommOutput, SSL3_CT_APPLICATIONDATA);
  856. if(pctRet != PCT_ERR_OK)
  857. {
  858. SP_RETURN(SP_LOG_RESULT(pctRet));
  859. }
  860. SetWrapNoEncrypt(pCommOutput->pvBuffer,
  861. SSL3_CT_APPLICATIONDATA,
  862. cbMessage - sizeof(SWRAP));
  863. if(pContext->RipeZombie->fProtocol & SP_PROT_TLS1)
  864. {
  865. ((PUCHAR)pCommOutput->pvBuffer)[02] = TLS1_CLIENT_VERSION_LSB;
  866. }
  867. DebugLog((DEB_TRACE, "Output: cbData:0x%x, cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  868. pCommOutput->cbData,
  869. pCommOutput->cbBuffer,
  870. pCommOutput->pvBuffer));
  871. SP_RETURN(PCT_ERR_OK);
  872. }
  873. //+---------------------------------------------------------------------------
  874. //
  875. // Function: Ssl3DecryptMessage
  876. //
  877. // Synopsis: Decode an SSL3 record.
  878. //
  879. // Arguments: [pContext] -- Schannel context.
  880. // [pMessage] -- Data from the remote party.
  881. // [pAppOutput] -- (output) Decrypted data.
  882. //
  883. // History: 10-22-97 jbanes CAPI integrated.
  884. //
  885. // Notes: The number of input data bytes consumed by this function
  886. // is returned in pMessage->cbData.
  887. //
  888. //----------------------------------------------------------------------------
  889. SP_STATUS WINAPI
  890. Ssl3DecryptMessage( PSPContext pContext,
  891. PSPBuffer pMessage,
  892. PSPBuffer pAppOutput)
  893. {
  894. SP_STATUS pctRet;
  895. SPBuffer Clean;
  896. SPBuffer Encrypted;
  897. UCHAR rgbDigest[SP_MAX_DIGEST_LEN];
  898. PUCHAR pbMAC;
  899. DWORD dwLength, cbActualData;
  900. SWRAP *pswrap = pMessage->pvBuffer;
  901. DWORD dwVersion;
  902. DWORD cbBlock;
  903. DWORD cbPadding;
  904. BOOL fBadPadding = FALSE;
  905. SP_BEGIN("Ssl3DecryptMessage");
  906. if((pContext == NULL) ||
  907. (pContext->pReadCipherInfo == NULL) ||
  908. (pContext->RipeZombie == NULL) ||
  909. (pAppOutput == NULL) ||
  910. (pMessage == NULL) ||
  911. (pMessage->pvBuffer == NULL))
  912. {
  913. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  914. }
  915. /* First determine the length of data, the length of padding,
  916. * and the location of data, and the location of MAC */
  917. cbActualData = pMessage->cbData;
  918. pMessage->cbData = sizeof(SWRAP); /* minimum amount of data we need */
  919. if(cbActualData < sizeof(SWRAP))
  920. {
  921. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  922. }
  923. dwVersion = COMBINEBYTES(pswrap->bMajor, pswrap->bMinor);
  924. if(dwVersion != SSL3_CLIENT_VERSION && dwVersion != TLS1_CLIENT_VERSION)
  925. {
  926. SP_RETURN(SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG));
  927. }
  928. dwLength = COMBINEBYTES(pswrap->bcbMSBSize, pswrap->bcbLSBSize);
  929. Encrypted.pvBuffer = (PUCHAR)pMessage->pvBuffer + sizeof(SWRAP);
  930. Encrypted.cbBuffer = pMessage->cbBuffer - sizeof(SWRAP);
  931. pMessage->cbData += dwLength ;
  932. if(pMessage->cbData > cbActualData)
  933. {
  934. SP_RETURN(PCT_INT_INCOMPLETE_MSG);
  935. }
  936. Encrypted.cbData = dwLength; /* encrypted data size */
  937. SP_ASSERT(Encrypted.cbData != 0);
  938. cbBlock = pContext->pReadCipherInfo->dwBlockSize;
  939. if(cbBlock > 1)
  940. {
  941. /* check to see if we have a block size violation */
  942. if((Encrypted.cbData % cbBlock) || (Encrypted.cbData < cbBlock))
  943. {
  944. SP_RETURN(SP_LOG_RESULT(PCT_INT_MSG_ALTERED));
  945. }
  946. }
  947. // Transfer the read key over from the application process.
  948. if(pContext->hReadKey == 0 &&
  949. pContext->pReadCipherInfo->aiCipher != CALG_NULLCIPHER)
  950. {
  951. DebugLog((DEB_TRACE, "Transfer read key from user process.\n"));
  952. pctRet = SPGetUserKeys(pContext, SCH_FLAG_READ_KEY);
  953. if(pctRet != PCT_ERR_OK)
  954. {
  955. return SP_LOG_RESULT(pctRet);
  956. }
  957. }
  958. // Decrypt message.
  959. if(pContext->pReadCipherInfo->aiCipher != CALG_NULLCIPHER)
  960. {
  961. if(!CryptDecrypt(pContext->hReadKey,
  962. 0, FALSE, 0,
  963. Encrypted.pvBuffer,
  964. &Encrypted.cbData))
  965. {
  966. SP_LOG_RESULT(GetLastError());
  967. SP_RETURN(PCT_INT_INTERNAL_ERROR);
  968. }
  969. }
  970. // Remove block cipher padding.
  971. if(cbBlock > 1)
  972. {
  973. // This is a block cipher.
  974. cbPadding = *((PUCHAR)Encrypted.pvBuffer + Encrypted.cbData - 1) + 1;
  975. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  976. {
  977. if(cbPadding > cbBlock || cbPadding >= Encrypted.cbData)
  978. {
  979. // Invalid pad size.
  980. DebugLog((DEB_WARN, "FINISHED Message: Padding Invalid\n"));
  981. fBadPadding = TRUE;
  982. }
  983. }
  984. else
  985. {
  986. if(cbPadding > 256 || cbPadding >= Encrypted.cbData)
  987. {
  988. // Invalid pad size.
  989. DebugLog((DEB_WARN, "FINISHED Message: Padding Invalid\n"));
  990. fBadPadding = TRUE;
  991. }
  992. }
  993. if(!fBadPadding)
  994. {
  995. Encrypted.cbData -= cbPadding;
  996. }
  997. }
  998. //
  999. // Note that if the padding is bogus we don't error out right
  1000. // away. This might give an attacker some timing information with
  1001. // which he can attack the symmetric cipher (or CBC) independently
  1002. // of the MAC. Instead, we'll perform the MAC operation and then
  1003. // error out.
  1004. //
  1005. // Build buffer over which to MAC.
  1006. if(Encrypted.cbData < pContext->pReadHashInfo->cbCheckSum)
  1007. {
  1008. fBadPadding = TRUE;
  1009. Clean.pvBuffer = Encrypted.pvBuffer;
  1010. Clean.cbData = Encrypted.cbData;
  1011. Clean.cbBuffer = Clean.cbData;
  1012. }
  1013. else
  1014. {
  1015. Clean.pvBuffer = Encrypted.pvBuffer;
  1016. Clean.cbData = Encrypted.cbData - pContext->pReadHashInfo->cbCheckSum;
  1017. Clean.cbBuffer = Clean.cbData;
  1018. }
  1019. // Validate MAC.
  1020. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  1021. {
  1022. pctRet = Ssl3ComputeMac(pContext,
  1023. TRUE,
  1024. &Clean,
  1025. pswrap->bCType,
  1026. rgbDigest,
  1027. sizeof(rgbDigest));
  1028. if(pctRet != PCT_ERR_OK)
  1029. {
  1030. return pctRet;
  1031. }
  1032. }
  1033. else
  1034. {
  1035. pctRet = Tls1ComputeMac(pContext,
  1036. TRUE,
  1037. &Clean,
  1038. pswrap->bCType,
  1039. rgbDigest,
  1040. sizeof(rgbDigest));
  1041. if(pctRet != PCT_ERR_OK)
  1042. {
  1043. return pctRet;
  1044. }
  1045. }
  1046. if(fBadPadding)
  1047. {
  1048. SP_RETURN(SP_LOG_RESULT(SEC_E_MESSAGE_ALTERED));
  1049. }
  1050. pContext->ReadCounter++;
  1051. pbMAC = (PUCHAR)Clean.pvBuffer + Clean.cbData;
  1052. if(memcmp(rgbDigest, pbMAC, pContext->pReadHashInfo->cbCheckSum))
  1053. {
  1054. DebugLog((DEB_WARN, "FINISHED Message: Checksum Invalid\n"));
  1055. if(pContext->RipeZombie->fProtocol & SP_PROT_TLS1)
  1056. {
  1057. SetTls1Alert(pContext, TLS1_ALERT_FATAL, TLS1_ALERT_BAD_RECORD_MAC);
  1058. }
  1059. SP_RETURN(SP_LOG_RESULT(SEC_E_MESSAGE_ALTERED));
  1060. }
  1061. if(pAppOutput->pvBuffer != Clean.pvBuffer)
  1062. {
  1063. CopyMemory(pAppOutput->pvBuffer, Clean.pvBuffer, Clean.cbData);
  1064. }
  1065. pAppOutput->cbData = Clean.cbData;
  1066. SP_RETURN(PCT_ERR_OK);
  1067. }
  1068. /*****************************************************************************/
  1069. // Create an encrypted Finish message, adding it to the end of the
  1070. // specified buffer object.
  1071. //
  1072. SP_STATUS SPBuildS3FinalFinish(PSPContext pContext, PSPBuffer pBuffer, BOOL fClient)
  1073. {
  1074. PBYTE pbMessage = (PBYTE)pBuffer->pvBuffer + pBuffer->cbData;
  1075. DWORD cbFinished;
  1076. SP_STATUS pctRet;
  1077. DWORD cbDataOut;
  1078. BYTE rgbMd5Digest[CB_MD5_DIGEST_LEN];
  1079. BYTE rgbSHADigest[CB_SHA_DIGEST_LEN];
  1080. // Build Finished message body.
  1081. pctRet = Ssl3BuildFinishMessage(pContext, rgbMd5Digest, rgbSHADigest, fClient);
  1082. if(pctRet != PCT_ERR_OK)
  1083. {
  1084. return pctRet;
  1085. }
  1086. CopyMemory(pbMessage + sizeof(SWRAP) + sizeof(SHSH),
  1087. rgbMd5Digest,
  1088. CB_MD5_DIGEST_LEN);
  1089. CopyMemory(pbMessage + sizeof(SWRAP) + sizeof(SHSH) + CB_MD5_DIGEST_LEN,
  1090. rgbSHADigest,
  1091. CB_SHA_DIGEST_LEN);
  1092. // Build Finished handshake header.
  1093. SetHandshake(pbMessage + sizeof(SWRAP),
  1094. SSL3_HS_FINISHED,
  1095. NULL,
  1096. CB_MD5_DIGEST_LEN + CB_SHA_DIGEST_LEN);
  1097. cbFinished = sizeof(SHSH) + CB_MD5_DIGEST_LEN + CB_SHA_DIGEST_LEN;
  1098. // Update handshake hash objects.
  1099. pctRet = UpdateHandshakeHash(pContext,
  1100. pbMessage + sizeof(SWRAP),
  1101. cbFinished,
  1102. FALSE);
  1103. if(pctRet != PCT_ERR_OK)
  1104. {
  1105. return(pctRet);
  1106. }
  1107. // Add record header and encrypt message.
  1108. pctRet = SPSetWrap(pContext,
  1109. pbMessage,
  1110. SSL3_CT_HANDSHAKE,
  1111. cbFinished,
  1112. fClient,
  1113. &cbDataOut);
  1114. if(pctRet != PCT_ERR_OK)
  1115. {
  1116. return pctRet;
  1117. }
  1118. // Update buffer length.
  1119. pBuffer->cbData += cbDataOut;
  1120. SP_ASSERT(pBuffer->cbData <= pBuffer->cbBuffer);
  1121. return PCT_ERR_OK;
  1122. }
  1123. SP_STATUS
  1124. SPSetWrap(
  1125. PSPContext pContext,
  1126. PUCHAR pbMessage,
  1127. UCHAR bContentType,
  1128. DWORD cbPayload,
  1129. BOOL fClient,
  1130. DWORD *pcbDataOut)
  1131. {
  1132. SWRAP *pswrap = (SWRAP *)pbMessage;
  1133. DWORD cbMessage;
  1134. SP_STATUS pctRet = PCT_ERR_OK;
  1135. // Compute size of encrypted message.
  1136. cbMessage = Ssl3CiphertextLen(pContext, cbPayload, fClient);
  1137. if(pContext->pWriteHashInfo)
  1138. {
  1139. SPBuffer Clean;
  1140. SPBuffer Encrypted;
  1141. Clean.pvBuffer = pbMessage + sizeof(SWRAP);
  1142. Clean.cbBuffer = cbMessage;
  1143. Clean.cbData = cbPayload;
  1144. Encrypted.pvBuffer = pbMessage;
  1145. Encrypted.cbBuffer = cbMessage;
  1146. Encrypted.cbData = cbPayload + sizeof(SWRAP);
  1147. pctRet = Ssl3EncryptRaw(pContext, &Clean, &Encrypted, bContentType);
  1148. cbMessage = Encrypted.cbData;
  1149. }
  1150. ZeroMemory(pswrap, sizeof(SWRAP));
  1151. pswrap->bCType = bContentType;
  1152. pswrap->bMajor = SSL3_CLIENT_VERSION_MSB;
  1153. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  1154. {
  1155. pswrap->bMinor = (UCHAR)SSL3_CLIENT_VERSION_LSB;
  1156. }
  1157. else
  1158. {
  1159. pswrap->bMinor = (UCHAR)TLS1_CLIENT_VERSION_LSB;
  1160. }
  1161. pswrap->bcbMSBSize = MSBOF(cbMessage - sizeof(SWRAP));
  1162. pswrap->bcbLSBSize = LSBOF(cbMessage - sizeof(SWRAP));
  1163. if(pcbDataOut != NULL)
  1164. {
  1165. *pcbDataOut = cbMessage;
  1166. }
  1167. return(pctRet);
  1168. }
  1169. void
  1170. SetWrapNoEncrypt(
  1171. PUCHAR pbMessage,
  1172. UCHAR bContentType,
  1173. DWORD cbPayload)
  1174. {
  1175. SWRAP *pswrap = (SWRAP *)pbMessage;
  1176. ZeroMemory(pswrap, sizeof(SWRAP));
  1177. pswrap->bCType = bContentType;
  1178. pswrap->bMajor = SSL3_CLIENT_VERSION_MSB;
  1179. pswrap->bMinor = SSL3_CLIENT_VERSION_LSB;
  1180. pswrap->bcbMSBSize = MSBOF(cbPayload);
  1181. pswrap->bcbLSBSize = LSBOF(cbPayload);
  1182. }
  1183. void SetHandshake(PUCHAR pb, BYTE bHandshake, PUCHAR pbData, DWORD dwSize)
  1184. {
  1185. SHSH *pshsh = (SHSH *) pb;
  1186. FillMemory(pshsh, sizeof(SHSH), 0);
  1187. pshsh->typHS = bHandshake;
  1188. pshsh->bcbMSB = MSBOF(dwSize) ;
  1189. pshsh->bcbLSB = LSBOF(dwSize) ;
  1190. if(NULL != pbData)
  1191. {
  1192. CopyMemory( pb + sizeof(SHSH) , pbData, dwSize);
  1193. }
  1194. }
  1195. //+---------------------------------------------------------------------------
  1196. //
  1197. // Function: UpdateHandshakeHash
  1198. //
  1199. // Synopsis:
  1200. //
  1201. // Arguments: [pContext] --
  1202. // [pb] --
  1203. // [dwcb] --
  1204. // [fInit] --
  1205. //
  1206. // History: 10-03-97 jbanes Added server-side CAPI integration.
  1207. //
  1208. // Notes:
  1209. //
  1210. //----------------------------------------------------------------------------
  1211. SP_STATUS
  1212. UpdateHandshakeHash(
  1213. PSPContext pContext,
  1214. PUCHAR pb,
  1215. DWORD dwcb,
  1216. BOOL fInit)
  1217. {
  1218. if(pContext->RipeZombie->hMasterProv == 0)
  1219. {
  1220. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1221. }
  1222. if(fInit)
  1223. {
  1224. DebugLog((DEB_TRACE, "UpdateHandshakeHash: initializing\n"));
  1225. if(pContext->hMd5Handshake)
  1226. {
  1227. CryptDestroyHash(pContext->hMd5Handshake);
  1228. pContext->hMd5Handshake = 0;
  1229. }
  1230. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  1231. CALG_MD5, 0, 0,
  1232. &pContext->hMd5Handshake))
  1233. {
  1234. SP_LOG_RESULT(GetLastError());
  1235. return PCT_INT_INTERNAL_ERROR;
  1236. }
  1237. if(pContext->hShaHandshake)
  1238. {
  1239. CryptDestroyHash(pContext->hShaHandshake);
  1240. pContext->hShaHandshake = 0;
  1241. }
  1242. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  1243. CALG_SHA, 0, 0,
  1244. &pContext->hShaHandshake))
  1245. {
  1246. SP_LOG_RESULT(GetLastError());
  1247. return PCT_INT_INTERNAL_ERROR;
  1248. }
  1249. }
  1250. if(pContext->hMd5Handshake == 0 || pContext->hShaHandshake == 0)
  1251. {
  1252. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1253. }
  1254. if(dwcb && NULL != pb)
  1255. {
  1256. DebugLog((DEB_TRACE, "UpdateHandshakeHash: %d bytes\n", dwcb));
  1257. if(!CryptHashData(pContext->hMd5Handshake,
  1258. pb, dwcb, 0))
  1259. {
  1260. SP_LOG_RESULT(GetLastError());
  1261. return PCT_INT_INTERNAL_ERROR;
  1262. }
  1263. if(!CryptHashData(pContext->hShaHandshake,
  1264. pb, dwcb, 0))
  1265. {
  1266. SP_LOG_RESULT(GetLastError());
  1267. return PCT_INT_INTERNAL_ERROR;
  1268. }
  1269. }
  1270. return PCT_ERR_OK;
  1271. }
  1272. //+---------------------------------------------------------------------------
  1273. //
  1274. // Function: Tls1ComputeCertVerifyHashes
  1275. //
  1276. // Synopsis: Compute the hashes contained by a TLS
  1277. // CertificateVerify message.
  1278. //
  1279. // Arguments: [pContext] -- Schannel context.
  1280. // [pbHash] --
  1281. // [cbHash] --
  1282. //
  1283. // History: 10-14-97 jbanes Created.
  1284. //
  1285. // Notes: The data generated by this routine is always 36 bytes in
  1286. // length, and consists of an MD5 hash followed by an SHA
  1287. // hash.
  1288. //
  1289. // The hash values are computed as:
  1290. //
  1291. // md5_hash = MD5(handshake_messages);
  1292. //
  1293. // sha_hash = SHA(handshake_messages);
  1294. //
  1295. //----------------------------------------------------------------------------
  1296. SP_STATUS
  1297. Tls1ComputeCertVerifyHashes(
  1298. PSPContext pContext, // in
  1299. PBYTE pbMD5, // out
  1300. PBYTE pbSHA) // out
  1301. {
  1302. HCRYPTHASH hHash = 0;
  1303. DWORD cbData;
  1304. if((pContext == NULL) ||
  1305. (pContext->RipeZombie == NULL))
  1306. {
  1307. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1308. }
  1309. if(pbMD5 != NULL)
  1310. {
  1311. // md5_hash = MD5(handshake_messages);
  1312. if(!CryptDuplicateHash(pContext->hMd5Handshake,
  1313. NULL,
  1314. 0,
  1315. &hHash))
  1316. {
  1317. SP_LOG_RESULT(GetLastError());
  1318. return PCT_INT_INTERNAL_ERROR;
  1319. }
  1320. cbData = CB_MD5_DIGEST_LEN;
  1321. if(!CryptGetHashParam(hHash,
  1322. HP_HASHVAL,
  1323. pbMD5,
  1324. &cbData,
  1325. 0))
  1326. {
  1327. SP_LOG_RESULT(GetLastError());
  1328. CryptDestroyHash(hHash);
  1329. return PCT_INT_INTERNAL_ERROR;
  1330. }
  1331. SP_ASSERT(cbData == CB_MD5_DIGEST_LEN);
  1332. if(!CryptDestroyHash(hHash))
  1333. {
  1334. SP_LOG_RESULT(GetLastError());
  1335. }
  1336. }
  1337. if(pbSHA != NULL)
  1338. {
  1339. // sha_hash = SHA(handshake_messages);
  1340. if(!CryptDuplicateHash(pContext->hShaHandshake,
  1341. NULL,
  1342. 0,
  1343. &hHash))
  1344. {
  1345. SP_LOG_RESULT(GetLastError());
  1346. return PCT_INT_INTERNAL_ERROR;
  1347. }
  1348. cbData = CB_SHA_DIGEST_LEN;
  1349. if(!CryptGetHashParam(hHash,
  1350. HP_HASHVAL, pbSHA,
  1351. &cbData,
  1352. 0))
  1353. {
  1354. SP_LOG_RESULT(GetLastError());
  1355. CryptDestroyHash(hHash);
  1356. return PCT_INT_INTERNAL_ERROR;
  1357. }
  1358. SP_ASSERT(cbData == CB_SHA_DIGEST_LEN);
  1359. if(!CryptDestroyHash(hHash))
  1360. {
  1361. SP_LOG_RESULT(GetLastError());
  1362. }
  1363. }
  1364. return PCT_ERR_OK;
  1365. }
  1366. //+---------------------------------------------------------------------------
  1367. //
  1368. // Function: Ssl3ComputeCertVerifyHashes
  1369. //
  1370. // Synopsis: Compute the hashes contained by an SSL3
  1371. // CertificateVerify message.
  1372. //
  1373. // Arguments: [pContext] -- Schannel context.
  1374. // [pbHash] --
  1375. // [cbHash] --
  1376. //
  1377. // History: 10-14-97 jbanes Added CAPI integration.
  1378. //
  1379. // Notes: The data generated by this routine is always 36 bytes in
  1380. // length, and consists of an MD5 hash followed by an SHA
  1381. // hash.
  1382. //
  1383. // The hash values are computed as follows:
  1384. //
  1385. // md5_hash = MD5(master_secret + pad2 +
  1386. // MD5(handshake_messages + master_secret +
  1387. // pad1));
  1388. //
  1389. // sha_hash = SHA(master_secret + pad2 +
  1390. // SHA(handshake_messages + master_secret +
  1391. // pad1));
  1392. //
  1393. //----------------------------------------------------------------------------
  1394. SP_STATUS
  1395. Ssl3ComputeCertVerifyHashes(
  1396. PSPContext pContext, // in
  1397. PBYTE pbMD5, // out
  1398. PBYTE pbSHA) // out
  1399. {
  1400. BYTE rgbPad1[CB_SSL3_MAX_MAC_PAD];
  1401. BYTE rgbPad2[CB_SSL3_MAX_MAC_PAD];
  1402. HCRYPTHASH hHash = 0;
  1403. DWORD cbData;
  1404. SP_STATUS pctRet;
  1405. FillMemory(rgbPad1, sizeof(rgbPad1), PAD1_CONSTANT);
  1406. FillMemory(rgbPad2, sizeof(rgbPad2), PAD2_CONSTANT);
  1407. if(pbMD5 != NULL)
  1408. {
  1409. //
  1410. // CertificateVerify.signature.md5_hash = MD5(master_secret + pad2 +
  1411. // MD5(handshake_messages + master_secret + pad1));
  1412. //
  1413. // Compute inner hash.
  1414. if(!CryptDuplicateHash(pContext->hMd5Handshake,
  1415. NULL,
  1416. 0,
  1417. &hHash))
  1418. {
  1419. SP_LOG_RESULT(GetLastError());
  1420. pctRet = PCT_INT_INTERNAL_ERROR;
  1421. goto cleanup;
  1422. }
  1423. if(!CryptHashSessionKey(hHash,
  1424. pContext->RipeZombie->hMasterKey,
  1425. CRYPT_LITTLE_ENDIAN))
  1426. {
  1427. SP_LOG_RESULT(GetLastError());
  1428. pctRet = PCT_INT_INTERNAL_ERROR;
  1429. goto cleanup;
  1430. }
  1431. if(!CryptHashData(hHash,
  1432. rgbPad1,
  1433. CB_SSL3_MD5_MAC_PAD,
  1434. 0))
  1435. {
  1436. SP_LOG_RESULT(GetLastError());
  1437. pctRet = PCT_INT_INTERNAL_ERROR;
  1438. goto cleanup;
  1439. }
  1440. cbData = CB_MD5_DIGEST_LEN;
  1441. if(!CryptGetHashParam(hHash,
  1442. HP_HASHVAL,
  1443. pbMD5,
  1444. &cbData,
  1445. 0))
  1446. {
  1447. SP_LOG_RESULT(GetLastError());
  1448. pctRet = PCT_INT_INTERNAL_ERROR;
  1449. goto cleanup;
  1450. }
  1451. SP_ASSERT(cbData == CB_MD5_DIGEST_LEN);
  1452. if(!CryptDestroyHash(hHash))
  1453. {
  1454. SP_LOG_RESULT(GetLastError());
  1455. }
  1456. hHash = 0;
  1457. // Compute outer hash.
  1458. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  1459. CALG_MD5,
  1460. 0,
  1461. 0,
  1462. &hHash))
  1463. {
  1464. SP_LOG_RESULT(GetLastError());
  1465. pctRet = PCT_INT_INTERNAL_ERROR;
  1466. goto cleanup;
  1467. }
  1468. if(!CryptHashSessionKey(hHash,
  1469. pContext->RipeZombie->hMasterKey,
  1470. CRYPT_LITTLE_ENDIAN))
  1471. {
  1472. SP_LOG_RESULT(GetLastError());
  1473. pctRet = PCT_INT_INTERNAL_ERROR;
  1474. goto cleanup;
  1475. }
  1476. if(!CryptHashData(hHash,
  1477. rgbPad2,
  1478. CB_SSL3_MD5_MAC_PAD,
  1479. 0))
  1480. {
  1481. SP_LOG_RESULT(GetLastError());
  1482. pctRet = PCT_INT_INTERNAL_ERROR;
  1483. goto cleanup;
  1484. }
  1485. if(!CryptHashData(hHash,
  1486. pbMD5,
  1487. CB_MD5_DIGEST_LEN,
  1488. 0))
  1489. {
  1490. SP_LOG_RESULT(GetLastError());
  1491. pctRet = PCT_INT_INTERNAL_ERROR;
  1492. goto cleanup;
  1493. }
  1494. cbData = CB_MD5_DIGEST_LEN;
  1495. if(!CryptGetHashParam(hHash,
  1496. HP_HASHVAL,
  1497. pbMD5,
  1498. &cbData,
  1499. 0))
  1500. {
  1501. SP_LOG_RESULT(GetLastError());
  1502. pctRet = PCT_INT_INTERNAL_ERROR;
  1503. goto cleanup;
  1504. }
  1505. SP_ASSERT(cbData == CB_MD5_DIGEST_LEN);
  1506. if(!CryptDestroyHash(hHash))
  1507. {
  1508. SP_LOG_RESULT(GetLastError());
  1509. }
  1510. hHash = 0;
  1511. }
  1512. if(pbSHA != NULL)
  1513. {
  1514. //
  1515. // CertificateVerify.signature.sha_hash = SHA(master_secret + pad2 +
  1516. // SHA(handshake_messages + master_secret + pad1));
  1517. //
  1518. // Compute inner hash.
  1519. if(!CryptDuplicateHash(pContext->hShaHandshake,
  1520. NULL,
  1521. 0,
  1522. &hHash))
  1523. {
  1524. SP_LOG_RESULT(GetLastError());
  1525. pctRet = PCT_INT_INTERNAL_ERROR;
  1526. goto cleanup;
  1527. }
  1528. if(!CryptHashSessionKey(hHash,
  1529. pContext->RipeZombie->hMasterKey,
  1530. CRYPT_LITTLE_ENDIAN))
  1531. {
  1532. SP_LOG_RESULT(GetLastError());
  1533. pctRet = PCT_INT_INTERNAL_ERROR;
  1534. goto cleanup;
  1535. }
  1536. if(!CryptHashData(hHash,
  1537. rgbPad1,
  1538. CB_SSL3_SHA_MAC_PAD,
  1539. 0))
  1540. {
  1541. SP_LOG_RESULT(GetLastError());
  1542. pctRet = PCT_INT_INTERNAL_ERROR;
  1543. goto cleanup;
  1544. }
  1545. cbData = CB_SHA_DIGEST_LEN;
  1546. if(!CryptGetHashParam(hHash,
  1547. HP_HASHVAL,
  1548. pbSHA,
  1549. &cbData,
  1550. 0))
  1551. {
  1552. SP_LOG_RESULT(GetLastError());
  1553. pctRet = PCT_INT_INTERNAL_ERROR;
  1554. goto cleanup;
  1555. }
  1556. SP_ASSERT(cbData == CB_SHA_DIGEST_LEN);
  1557. if(!CryptDestroyHash(hHash))
  1558. {
  1559. SP_LOG_RESULT(GetLastError());
  1560. }
  1561. hHash = 0;
  1562. // Compute outer hash.
  1563. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  1564. CALG_SHA, 0, 0,
  1565. &hHash))
  1566. {
  1567. SP_LOG_RESULT(GetLastError());
  1568. pctRet = PCT_INT_INTERNAL_ERROR;
  1569. goto cleanup;
  1570. }
  1571. if(!CryptHashSessionKey(hHash,
  1572. pContext->RipeZombie->hMasterKey,
  1573. CRYPT_LITTLE_ENDIAN))
  1574. {
  1575. SP_LOG_RESULT(GetLastError());
  1576. pctRet = PCT_INT_INTERNAL_ERROR;
  1577. goto cleanup;
  1578. }
  1579. if(!CryptHashData(hHash,
  1580. rgbPad2,
  1581. CB_SSL3_SHA_MAC_PAD,
  1582. 0))
  1583. {
  1584. SP_LOG_RESULT(GetLastError());
  1585. pctRet = PCT_INT_INTERNAL_ERROR;
  1586. goto cleanup;
  1587. }
  1588. if(!CryptHashData(hHash,
  1589. pbSHA,
  1590. CB_SHA_DIGEST_LEN,
  1591. 0))
  1592. {
  1593. SP_LOG_RESULT(GetLastError());
  1594. pctRet = PCT_INT_INTERNAL_ERROR;
  1595. goto cleanup;
  1596. }
  1597. cbData = CB_SHA_DIGEST_LEN;
  1598. if(!CryptGetHashParam(hHash,
  1599. HP_HASHVAL,
  1600. pbSHA,
  1601. &cbData,
  1602. 0))
  1603. {
  1604. SP_LOG_RESULT(GetLastError());
  1605. pctRet = PCT_INT_INTERNAL_ERROR;
  1606. goto cleanup;
  1607. }
  1608. SP_ASSERT(cbData == CB_SHA_DIGEST_LEN);
  1609. if(!CryptDestroyHash(hHash))
  1610. {
  1611. SP_LOG_RESULT(GetLastError());
  1612. }
  1613. hHash = 0;
  1614. }
  1615. pctRet = PCT_ERR_OK;
  1616. cleanup:
  1617. if(hHash)
  1618. {
  1619. CryptDestroyHash(hHash);
  1620. }
  1621. return pctRet;
  1622. }
  1623. SP_STATUS Ssl3HandleCCS(PSPContext pContext,
  1624. PUCHAR pb,
  1625. DWORD cbMessage)
  1626. {
  1627. SP_STATUS pctRet = PCT_ERR_OK;
  1628. BOOL fSender =
  1629. (0 == (pContext->RipeZombie->fProtocol & SP_PROT_SSL3TLS1_CLIENTS)) ;
  1630. SP_BEGIN("Ssl3HandleCCS");
  1631. if(cbMessage != 1 || pb[0] != 0x1)
  1632. {
  1633. pctRet = SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  1634. SP_RETURN(pctRet);
  1635. }
  1636. // We always zero out the read counter on receipt
  1637. // of a change cipher spec message.
  1638. pContext->ReadCounter = 0;
  1639. // Move pending ciphers to real ciphers
  1640. pctRet = ContextInitCiphers(pContext, TRUE, FALSE);
  1641. if(pctRet != PCT_ERR_OK)
  1642. {
  1643. SP_RETURN(pctRet);
  1644. }
  1645. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  1646. {
  1647. pctRet = Ssl3MakeReadSessionKeys(pContext);
  1648. }
  1649. else
  1650. {
  1651. pctRet = Tls1MakeReadSessionKeys(pContext);
  1652. }
  1653. if(pctRet != PCT_ERR_OK)
  1654. {
  1655. SP_RETURN(pctRet);
  1656. }
  1657. if(fSender)
  1658. {
  1659. pContext->wS3CipherSuiteClient = (WORD)UniAvailableCiphers[pContext->dwPendingCipherSuiteIndex].CipherKind;
  1660. pContext->State = SSL3_STATE_CHANGE_CIPHER_SPEC_SERVER;
  1661. }
  1662. else
  1663. {
  1664. pContext->wS3CipherSuiteServer = (WORD)UniAvailableCiphers[pContext->dwPendingCipherSuiteIndex].CipherKind;
  1665. pContext->State = SSL3_STATE_CHANGE_CIPHER_SPEC_CLIENT;
  1666. }
  1667. SP_RETURN(PCT_ERR_OK);
  1668. }
  1669. /*****************************************************************************/
  1670. // Create a (possibly encrypted) ChangeCipherSpec and an encrypted
  1671. // Finish message, adding them to the end of the specified buffer object.
  1672. //
  1673. SP_STATUS
  1674. BuildCCSAndFinishMessage(
  1675. PSPContext pContext,
  1676. PSPBuffer pBuffer,
  1677. BOOL fClient)
  1678. {
  1679. SP_STATUS pctRet;
  1680. PBYTE pbMessage = (PBYTE)pBuffer->pvBuffer + pBuffer->cbData;
  1681. DWORD cbDataOut;
  1682. // Build ChangeCipherSpec message body.
  1683. *(pbMessage + sizeof(SWRAP)) = 0x1;
  1684. // Add record header and encrypt message.
  1685. pctRet = SPSetWrap(pContext,
  1686. pbMessage,
  1687. SSL3_CT_CHANGE_CIPHER_SPEC,
  1688. 1,
  1689. fClient,
  1690. &cbDataOut);
  1691. if(pctRet != PCT_ERR_OK)
  1692. return(pctRet);
  1693. // Update buffer length.
  1694. pBuffer->cbData += cbDataOut;
  1695. SP_ASSERT(pBuffer->cbData <= pBuffer->cbBuffer);
  1696. // Update cipher suites.
  1697. pContext->WriteCounter = 0;
  1698. pctRet = ContextInitCiphers(pContext, FALSE, TRUE);
  1699. if(pctRet != PCT_ERR_OK)
  1700. {
  1701. return(pctRet);
  1702. }
  1703. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  1704. {
  1705. pctRet = Ssl3MakeWriteSessionKeys(pContext);
  1706. }
  1707. else
  1708. {
  1709. pctRet = Tls1MakeWriteSessionKeys(pContext);
  1710. }
  1711. if(pctRet != PCT_ERR_OK)
  1712. {
  1713. return(pctRet);
  1714. }
  1715. if(fClient)
  1716. {
  1717. pContext->wS3CipherSuiteClient = (WORD)UniAvailableCiphers[pContext->dwPendingCipherSuiteIndex].CipherKind;
  1718. }
  1719. else
  1720. {
  1721. pContext->wS3CipherSuiteServer = (WORD)UniAvailableCiphers[pContext->dwPendingCipherSuiteIndex].CipherKind;
  1722. }
  1723. // Build Finish message.
  1724. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3)
  1725. {
  1726. pctRet = SPBuildS3FinalFinish(pContext, pBuffer, fClient);
  1727. }
  1728. else
  1729. {
  1730. pctRet = SPBuildTls1FinalFinish(pContext, pBuffer, fClient);
  1731. }
  1732. return pctRet;
  1733. }
  1734. SP_STATUS
  1735. Ssl3SelectCipher
  1736. (
  1737. PSPContext pContext,
  1738. WORD wCipher
  1739. )
  1740. {
  1741. SP_STATUS pctRet=PCT_ERR_ILLEGAL_MESSAGE;
  1742. DWORD i;
  1743. PCipherInfo pCipherInfo = NULL;
  1744. PHashInfo pHashInfo = NULL;
  1745. PKeyExchangeInfo pExchInfo = NULL;
  1746. pContext->dwPendingCipherSuiteIndex = 0;
  1747. for(i = 0; i < UniNumCiphers; i++)
  1748. {
  1749. // Is this an SSL3 cipher suite?
  1750. if(!(UniAvailableCiphers[i].fProt & pContext->RipeZombie->fProtocol))
  1751. {
  1752. continue;
  1753. }
  1754. // Is this the right cipher suite?
  1755. if(UniAvailableCiphers[i].CipherKind != wCipher)
  1756. {
  1757. continue;
  1758. }
  1759. pCipherInfo = GetCipherInfo(UniAvailableCiphers[i].aiCipher, UniAvailableCiphers[i].dwStrength);
  1760. pHashInfo = GetHashInfo(UniAvailableCiphers[i].aiHash);
  1761. pExchInfo = GetKeyExchangeInfo(UniAvailableCiphers[i].KeyExch);
  1762. if(!IsCipherAllowed(pContext,
  1763. pCipherInfo,
  1764. pContext->RipeZombie->fProtocol,
  1765. pContext->RipeZombie->dwCF))
  1766. {
  1767. continue;
  1768. }
  1769. if(!IsHashAllowed(pContext, pHashInfo, pContext->RipeZombie->fProtocol))
  1770. {
  1771. continue;
  1772. }
  1773. if(!IsExchAllowed(pContext, pExchInfo, pContext->RipeZombie->fProtocol))
  1774. {
  1775. continue;
  1776. }
  1777. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3TLS1_SERVERS)
  1778. {
  1779. // Determine the credentials (and CSP) to use, based on the
  1780. // key exchange algorithm.
  1781. pctRet = SPPickClientCertificate(pContext,
  1782. UniAvailableCiphers[i].KeyExch);
  1783. if(pctRet != PCT_ERR_OK)
  1784. {
  1785. continue;
  1786. }
  1787. }
  1788. pContext->RipeZombie->dwCipherSuiteIndex = i;
  1789. pContext->RipeZombie->aiCipher = UniAvailableCiphers[i].aiCipher;
  1790. pContext->RipeZombie->dwStrength = UniAvailableCiphers[i].dwStrength;
  1791. pContext->RipeZombie->aiHash = UniAvailableCiphers[i].aiHash;
  1792. pContext->RipeZombie->SessExchSpec = UniAvailableCiphers[i].KeyExch;
  1793. return ContextInitCiphersFromCache(pContext);
  1794. }
  1795. return(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  1796. }
  1797. // Server side cipher selection
  1798. SP_STATUS
  1799. Ssl3SelectCipherEx(
  1800. PSPContext pContext,
  1801. DWORD *pCipherSpecs,
  1802. DWORD cCipherSpecs)
  1803. {
  1804. DWORD i, j;
  1805. SP_STATUS pctRet;
  1806. PCipherInfo pCipherInfo = NULL;
  1807. PHashInfo pHashInfo = NULL;
  1808. PKeyExchangeInfo pExchInfo = NULL;
  1809. PSPCredential pCred = NULL;
  1810. BOOL fFound;
  1811. pContext->dwPendingCipherSuiteIndex = 0;
  1812. // Loop through the supported SSL3 cipher suites.
  1813. for(i = 0; i < UniNumCiphers; i++)
  1814. {
  1815. // Is this an SSL3 cipher suite?
  1816. if(!(UniAvailableCiphers[i].fProt & pContext->RipeZombie->fProtocol))
  1817. {
  1818. continue;
  1819. }
  1820. pCipherInfo = GetCipherInfo(UniAvailableCiphers[i].aiCipher,
  1821. UniAvailableCiphers[i].dwStrength);
  1822. pHashInfo = GetHashInfo(UniAvailableCiphers[i].aiHash);
  1823. pExchInfo = GetKeyExchangeInfo(UniAvailableCiphers[i].KeyExch);
  1824. // Do we currently support this hash and key exchange algorithm?
  1825. if(!IsHashAllowed(pContext, pHashInfo, pContext->RipeZombie->fProtocol))
  1826. {
  1827. DebugLog((DEB_TRACE, "Cipher %d - hash not supported\n", i));
  1828. continue;
  1829. }
  1830. if(!IsExchAllowed(pContext, pExchInfo, pContext->RipeZombie->fProtocol))
  1831. {
  1832. DebugLog((DEB_TRACE, "Cipher %d - exch not supported\n", i));
  1833. continue;
  1834. }
  1835. // Do we have an appropriate certificate?
  1836. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL3TLS1_SERVERS)
  1837. {
  1838. pctRet = SPPickServerCertificate(pContext,
  1839. UniAvailableCiphers[i].KeyExch);
  1840. if(pctRet != PCT_ERR_OK)
  1841. {
  1842. DebugLog((DEB_TRACE, "Cipher %d - certificate %d not found\n",
  1843. i, UniAvailableCiphers[i].KeyExch));
  1844. continue;
  1845. }
  1846. }
  1847. pCred = pContext->RipeZombie->pActiveServerCred;
  1848. // Do we support this encryption algorithm/key length?
  1849. if(!IsCipherSuiteAllowed(pContext,
  1850. pCipherInfo,
  1851. pContext->RipeZombie->fProtocol,
  1852. pCred->dwCertFlags,
  1853. UniAvailableCiphers[i].dwFlags))
  1854. {
  1855. DebugLog((DEB_TRACE, "Cipher %d - cipher not supported\n", i));
  1856. continue;
  1857. }
  1858. // Is this cipher suite supported by the client?
  1859. for(fFound = FALSE, j = 0; j < cCipherSpecs; j++)
  1860. {
  1861. if(UniAvailableCiphers[i].CipherKind == pCipherSpecs[j])
  1862. {
  1863. fFound = TRUE;
  1864. break;
  1865. }
  1866. }
  1867. if(!fFound)
  1868. {
  1869. DebugLog((DEB_TRACE, "Cipher %d - not supported by client\n", i));
  1870. continue;
  1871. }
  1872. if(UniAvailableCiphers[i].KeyExch == SP_EXCH_RSA_PKCS1)
  1873. {
  1874. // This is an RSA cipher suite, so make sure that the
  1875. // CSP supports it.
  1876. if(!IsAlgSupportedCapi(pContext->RipeZombie->fProtocol,
  1877. UniAvailableCiphers + i,
  1878. pCred->pCapiAlgs,
  1879. pCred->cCapiAlgs))
  1880. {
  1881. DebugLog((DEB_TRACE, "Cipher %d - not supported by csp\n", i));
  1882. continue;
  1883. }
  1884. }
  1885. if(UniAvailableCiphers[i].KeyExch == SP_EXCH_DH_PKCS3)
  1886. {
  1887. // This is a DH cipher suite, so make sure that the
  1888. // CSP supports it.
  1889. if(!IsAlgSupportedCapi(pContext->RipeZombie->fProtocol,
  1890. UniAvailableCiphers + i,
  1891. pCred->pCapiAlgs,
  1892. pCred->cCapiAlgs))
  1893. {
  1894. DebugLog((DEB_TRACE, "Cipher %d - not supported by csp\n", i));
  1895. continue;
  1896. }
  1897. }
  1898. // Use this cipher.
  1899. pContext->RipeZombie->dwCipherSuiteIndex = i;
  1900. pContext->RipeZombie->aiCipher = UniAvailableCiphers[i].aiCipher;
  1901. pContext->RipeZombie->dwStrength = UniAvailableCiphers[i].dwStrength;
  1902. pContext->RipeZombie->aiHash = UniAvailableCiphers[i].aiHash;
  1903. pContext->RipeZombie->SessExchSpec = UniAvailableCiphers[i].KeyExch;
  1904. pContext->RipeZombie->dwCF = pCred->dwCertFlags;
  1905. return ContextInitCiphersFromCache(pContext);
  1906. }
  1907. LogCipherMismatchEvent();
  1908. return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  1909. }
  1910. /*****************************************************************************/
  1911. VOID ComputeServerExchangeHashes(
  1912. PSPContext pContext,
  1913. PBYTE pbServerParams, // in
  1914. INT iServerParamsLen, // in
  1915. PBYTE pbMd5HashVal, // out
  1916. PBYTE pbShaHashVal) // out
  1917. {
  1918. MD5_CTX Md5Hash;
  1919. A_SHA_CTX ShaHash;
  1920. //
  1921. // md5_hash = MD5(ClientHello.random + ServerHello.random + ServerParams);
  1922. //
  1923. // sha_hash = SHA(ClientHello.random + ServerHello.random + ServerParams);
  1924. //
  1925. MD5Init(&Md5Hash);
  1926. MD5Update(&Md5Hash, pContext->rgbS3CRandom, 32);
  1927. MD5Update(&Md5Hash, pContext->rgbS3SRandom, 32);
  1928. MD5Update(&Md5Hash, pbServerParams, iServerParamsLen);
  1929. MD5Final(&Md5Hash);
  1930. CopyMemory(pbMd5HashVal, Md5Hash.digest, 16);
  1931. A_SHAInit(&ShaHash);
  1932. A_SHAUpdate(&ShaHash, pContext->rgbS3CRandom, 32);
  1933. A_SHAUpdate(&ShaHash, pContext->rgbS3SRandom, 32);
  1934. A_SHAUpdate(&ShaHash, pbServerParams, iServerParamsLen);
  1935. A_SHAFinal(&ShaHash, pbShaHashVal);
  1936. }
  1937. SP_STATUS
  1938. UnwrapSsl3Message(
  1939. PSPContext pContext,
  1940. PSPBuffer pMsgInput)
  1941. {
  1942. SPBuffer Encrypted;
  1943. SPBuffer Clean;
  1944. SP_STATUS pctRet;
  1945. SWRAP *pswrap = (SWRAP *)pMsgInput->pvBuffer;
  1946. PBYTE pbMsg = (PBYTE)pMsgInput->pvBuffer;
  1947. //
  1948. // Validate 5 byte header.
  1949. //
  1950. // ProtocolVersion version;
  1951. if(COMBINEBYTES(pbMsg[1], pbMsg[2]) < SSL3_CLIENT_VERSION)
  1952. {
  1953. pctRet = SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  1954. }
  1955. if(COMBINEBYTES(pswrap->bcbMSBSize, pswrap->bcbLSBSize) <
  1956. pContext->pReadHashInfo->cbCheckSum)
  1957. {
  1958. return(PCT_ERR_ILLEGAL_MESSAGE);
  1959. }
  1960. Encrypted.pvBuffer = pMsgInput->pvBuffer;
  1961. Encrypted.cbBuffer = pMsgInput->cbBuffer;
  1962. Encrypted.cbData = pMsgInput->cbData;
  1963. Clean.pvBuffer = (PUCHAR)pMsgInput->pvBuffer + sizeof(SWRAP);
  1964. pctRet = Ssl3DecryptMessage(pContext, &Encrypted, &Clean);
  1965. if(pctRet == PCT_ERR_OK)
  1966. {
  1967. pswrap->bcbMSBSize = MSBOF(Clean.cbData);
  1968. pswrap->bcbLSBSize = LSBOF(Clean.cbData);
  1969. }
  1970. return(pctRet);
  1971. }
  1972. SP_STATUS
  1973. ParseAlertMessage(
  1974. PSPContext pContext,
  1975. PUCHAR pbAlertMsg,
  1976. DWORD cbMessage
  1977. )
  1978. {
  1979. SP_STATUS pctRet=PCT_ERR_OK;
  1980. if(cbMessage != 2)
  1981. {
  1982. return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  1983. }
  1984. if(pbAlertMsg[0] != SSL3_ALERT_WARNING && pbAlertMsg[0] != SSL3_ALERT_FATAL)
  1985. {
  1986. return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  1987. }
  1988. DebugLog((DEB_WARN, "AlertMessage, Alert Level - %lx\n", (DWORD)pbAlertMsg[0]));
  1989. DebugLog((DEB_WARN, "AlertMessage, Alert Description - %lx\n", (DWORD)pbAlertMsg[1]));
  1990. if(pbAlertMsg[0] == SSL3_ALERT_WARNING)
  1991. {
  1992. switch(pbAlertMsg[1])
  1993. {
  1994. case SSL3_ALERT_NO_CERTIFICATE:
  1995. DebugLog((DEB_TRACE, "no_certificate alert\n"));
  1996. pContext->State = SSL3_STATE_NO_CERT_ALERT;
  1997. pctRet = PCT_ERR_OK;
  1998. break;
  1999. case SSL3_ALERT_CLOSE_NOTIFY:
  2000. DebugLog((DEB_TRACE, "close_notify alert\n"));
  2001. pctRet = SEC_I_CONTEXT_EXPIRED;
  2002. break;
  2003. default:
  2004. DebugLog((DEB_TRACE, "Ignoring warning alert\n"));
  2005. pctRet = PCT_ERR_OK;
  2006. break;
  2007. }
  2008. }
  2009. else
  2010. {
  2011. switch(pbAlertMsg[1])
  2012. {
  2013. case SSL3_ALERT_UNEXPECTED_MESSAGE:
  2014. DebugLog((DEB_TRACE, "unexpected_message alert\n"));
  2015. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2016. break;
  2017. case TLS1_ALERT_BAD_RECORD_MAC:
  2018. DebugLog((DEB_TRACE, "bad_record_mac alert\n"));
  2019. pctRet = SP_LOG_RESULT(SEC_E_MESSAGE_ALTERED);
  2020. break;
  2021. case TLS1_ALERT_DECRYPTION_FAILED:
  2022. DebugLog((DEB_TRACE, "decryption_failed alert\n"));
  2023. pctRet = SP_LOG_RESULT(SEC_E_DECRYPT_FAILURE);
  2024. break;
  2025. case TLS1_ALERT_RECORD_OVERFLOW:
  2026. DebugLog((DEB_TRACE, "record_overflow alert\n"));
  2027. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2028. break;
  2029. case SSL3_ALERT_DECOMPRESSION_FAIL:
  2030. DebugLog((DEB_TRACE, "decompression_fail alert\n"));
  2031. pctRet = SP_LOG_RESULT(SEC_E_MESSAGE_ALTERED);
  2032. break;
  2033. case SSL3_ALERT_HANDSHAKE_FAILURE:
  2034. DebugLog((DEB_TRACE, "handshake_failure alert\n"));
  2035. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2036. break;
  2037. case TLS1_ALERT_BAD_CERTIFICATE:
  2038. DebugLog((DEB_TRACE, "bad_certificate alert\n"));
  2039. pctRet = SP_LOG_RESULT(SEC_E_CERT_UNKNOWN);
  2040. break;
  2041. case TLS1_ALERT_UNSUPPORTED_CERT:
  2042. DebugLog((DEB_TRACE, "unsupported_cert alert\n"));
  2043. pctRet = SP_LOG_RESULT(SEC_E_CERT_UNKNOWN);
  2044. break;
  2045. case TLS1_ALERT_CERTIFICATE_REVOKED:
  2046. DebugLog((DEB_TRACE, "certificate_revoked alert\n"));
  2047. pctRet = SP_LOG_RESULT(CRYPT_E_REVOKED);
  2048. break;
  2049. case TLS1_ALERT_CERTIFICATE_EXPIRED:
  2050. DebugLog((DEB_TRACE, "certificate_expired alert\n"));
  2051. pctRet = SP_LOG_RESULT(SEC_E_CERT_EXPIRED);
  2052. break;
  2053. case TLS1_ALERT_CERTIFICATE_UNKNOWN:
  2054. DebugLog((DEB_TRACE, "certificate_unknown alert\n"));
  2055. pctRet = SP_LOG_RESULT(SEC_E_CERT_UNKNOWN);
  2056. break;
  2057. case SSL3_ALERT_ILLEGAL_PARAMETER:
  2058. DebugLog((DEB_TRACE, "illegal_parameter alert\n"));
  2059. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2060. break;
  2061. case TLS1_ALERT_UNKNOWN_CA:
  2062. DebugLog((DEB_TRACE, "unknown_ca alert\n"));
  2063. pctRet = SP_LOG_RESULT(SEC_E_UNTRUSTED_ROOT);
  2064. break;
  2065. case TLS1_ALERT_ACCESS_DENIED:
  2066. DebugLog((DEB_TRACE, "access_denied alert\n"));
  2067. pctRet = SP_LOG_RESULT(SEC_E_LOGON_DENIED);
  2068. break;
  2069. case TLS1_ALERT_DECODE_ERROR:
  2070. DebugLog((DEB_TRACE, "decode_error alert\n"));
  2071. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2072. break;
  2073. case TLS1_ALERT_DECRYPT_ERROR:
  2074. DebugLog((DEB_TRACE, "decrypt_error alert\n"));
  2075. pctRet = SP_LOG_RESULT(SEC_E_DECRYPT_FAILURE);
  2076. break;
  2077. case TLS1_ALERT_EXPORT_RESTRICTION:
  2078. DebugLog((DEB_TRACE, "export_restriction alert\n"));
  2079. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2080. break;
  2081. case TLS1_ALERT_PROTOCOL_VERSION:
  2082. DebugLog((DEB_TRACE, "protocol_version alert\n"));
  2083. pctRet = SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
  2084. break;
  2085. case TLS1_ALERT_INSUFFIENT_SECURITY:
  2086. DebugLog((DEB_TRACE, "insuffient_security alert\n"));
  2087. pctRet = SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  2088. break;
  2089. case TLS1_ALERT_INTERNAL_ERROR:
  2090. DebugLog((DEB_TRACE, "internal_error alert\n"));
  2091. pctRet = SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  2092. break;
  2093. default:
  2094. DebugLog((DEB_TRACE, "Unknown fatal alert\n"));
  2095. pctRet = SP_LOG_RESULT(SEC_E_ILLEGAL_MESSAGE);
  2096. break;
  2097. }
  2098. }
  2099. return pctRet;
  2100. }
  2101. void BuildAlertMessage(PBYTE pbAlertMsg, UCHAR bAlertLevel, UCHAR bAlertDesc)
  2102. {
  2103. ALRT *palrt = (ALRT *) pbAlertMsg;
  2104. FillMemory(palrt, sizeof(ALRT), 0);
  2105. palrt->bCType = SSL3_CT_ALERT;
  2106. palrt->bMajor = SSL3_CLIENT_VERSION_MSB;
  2107. // palrt->bMinor = SSL3_CLIENT_VERSION_LSB; DONE by FillMemory
  2108. // palrt->bcbMSBSize = 0; Done by FillMemory
  2109. palrt->bcbLSBSize = 2;
  2110. palrt->bAlertLevel = bAlertLevel;
  2111. palrt->bAlertDesc = bAlertDesc ;
  2112. }
  2113. /*****************************************************************************/
  2114. // Create an encrypted Finish message, adding it to the end of the
  2115. // specified buffer object.
  2116. //
  2117. SP_STATUS SPBuildTls1FinalFinish(PSPContext pContext, PSPBuffer pBuffer, BOOL fClient)
  2118. {
  2119. PBYTE pbMessage = (PBYTE)pBuffer->pvBuffer + pBuffer->cbData;
  2120. DWORD cbFinished;
  2121. SP_STATUS pctRet;
  2122. DWORD cbDataOut;
  2123. BYTE rgbDigest[CB_TLS1_VERIFYDATA];
  2124. // Build Finished message body.
  2125. pctRet = Tls1BuildFinishMessage(pContext, rgbDigest, sizeof(rgbDigest), fClient);
  2126. if(pctRet != PCT_ERR_OK)
  2127. {
  2128. return pctRet;
  2129. }
  2130. CopyMemory(pbMessage + sizeof(SWRAP) + sizeof(SHSH),
  2131. rgbDigest,
  2132. CB_TLS1_VERIFYDATA);
  2133. // Build Finished handshake header.
  2134. SetHandshake(pbMessage + sizeof(SWRAP),
  2135. SSL3_HS_FINISHED,
  2136. NULL,
  2137. CB_TLS1_VERIFYDATA);
  2138. cbFinished = sizeof(SHSH) + CB_TLS1_VERIFYDATA;
  2139. // Update handshake hash objects.
  2140. pctRet = UpdateHandshakeHash(pContext,
  2141. pbMessage + sizeof(SWRAP),
  2142. cbFinished,
  2143. FALSE);
  2144. if(pctRet != PCT_ERR_OK)
  2145. {
  2146. return(pctRet);
  2147. }
  2148. // Add record header and encrypt message.
  2149. pctRet = SPSetWrap(pContext,
  2150. pbMessage,
  2151. SSL3_CT_HANDSHAKE,
  2152. cbFinished,
  2153. fClient,
  2154. &cbDataOut);
  2155. if(pctRet != PCT_ERR_OK)
  2156. {
  2157. return(pctRet);
  2158. }
  2159. // Update buffer length .
  2160. pBuffer->cbData += cbDataOut;
  2161. SP_ASSERT(pBuffer->cbData <= pBuffer->cbBuffer);
  2162. return pctRet;
  2163. }
  2164. //+---------------------------------------------------------------------------
  2165. //
  2166. // Function: Tls1BuildFinishMessage
  2167. //
  2168. // Synopsis: Compute a TLS MAC for the specified message.
  2169. //
  2170. // Arguments: [pContext] -- Schannel context.
  2171. // [pbVerifyData] -- Verify data buffer.
  2172. // [cbVerifyData] -- Length of verify data buffer.
  2173. // [fClient] -- Client-generated Finished?
  2174. //
  2175. // History: 10-13-97 jbanes Created.
  2176. //
  2177. // Notes: The Finished message is computed using the following formula:
  2178. //
  2179. // verify_data = PRF(master_secret, finished_label,
  2180. // MD5(handshake_messages) +
  2181. // SHA-1(handshake_messages)) [0..11];
  2182. //
  2183. //----------------------------------------------------------------------------
  2184. SP_STATUS
  2185. Tls1BuildFinishMessage(
  2186. PSPContext pContext, // in
  2187. PBYTE pbVerifyData, // out
  2188. DWORD cbVerifyData, // in
  2189. BOOL fClient) // in
  2190. {
  2191. PBYTE pbLabel;
  2192. DWORD cbLabel;
  2193. UCHAR rgbData[CB_MD5_DIGEST_LEN + CB_SHA_DIGEST_LEN];
  2194. DWORD cbData;
  2195. HCRYPTHASH hHash = 0;
  2196. CRYPT_DATA_BLOB Data;
  2197. SP_STATUS pctRet;
  2198. if(cbVerifyData < CB_TLS1_VERIFYDATA)
  2199. {
  2200. return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  2201. }
  2202. if(fClient)
  2203. {
  2204. pbLabel = (PBYTE)TLS1_LABEL_CLIENTFINISHED;
  2205. }
  2206. else
  2207. {
  2208. pbLabel = (PBYTE)TLS1_LABEL_SERVERFINISHED;
  2209. }
  2210. cbLabel = CB_TLS1_LABEL_FINISHED;
  2211. // Get the MD5 hash of the handshake messages so far.
  2212. if(!CryptDuplicateHash(pContext->hMd5Handshake,
  2213. NULL,
  2214. 0,
  2215. &hHash))
  2216. {
  2217. SP_LOG_RESULT(GetLastError());
  2218. pctRet = PCT_INT_INTERNAL_ERROR;
  2219. goto error;
  2220. }
  2221. cbData = CB_MD5_DIGEST_LEN;
  2222. if(!CryptGetHashParam(hHash,
  2223. HP_HASHVAL,
  2224. rgbData,
  2225. &cbData,
  2226. 0))
  2227. {
  2228. SP_LOG_RESULT(GetLastError());
  2229. pctRet = PCT_INT_INTERNAL_ERROR;
  2230. goto error;
  2231. }
  2232. if(!CryptDestroyHash(hHash))
  2233. {
  2234. SP_LOG_RESULT(GetLastError());
  2235. }
  2236. hHash = 0;
  2237. // Get the SHA hash of the handshake messages so far.
  2238. if(!CryptDuplicateHash(pContext->hShaHandshake,
  2239. NULL,
  2240. 0,
  2241. &hHash))
  2242. {
  2243. SP_LOG_RESULT(GetLastError());
  2244. pctRet = PCT_INT_INTERNAL_ERROR;
  2245. goto error;
  2246. }
  2247. cbData = A_SHA_DIGEST_LEN;
  2248. if(!CryptGetHashParam(hHash,
  2249. HP_HASHVAL,
  2250. rgbData + CB_MD5_DIGEST_LEN,
  2251. &cbData,
  2252. 0))
  2253. {
  2254. SP_LOG_RESULT(GetLastError());
  2255. pctRet = PCT_INT_INTERNAL_ERROR;
  2256. goto error;
  2257. }
  2258. cbData = CB_MD5_DIGEST_LEN + CB_SHA_DIGEST_LEN;
  2259. if(!CryptDestroyHash(hHash))
  2260. {
  2261. SP_LOG_RESULT(GetLastError());
  2262. }
  2263. hHash = 0;
  2264. // Compute the PRF
  2265. if(!CryptCreateHash(pContext->RipeZombie->hMasterProv,
  2266. CALG_TLS1PRF,
  2267. pContext->RipeZombie->hMasterKey,
  2268. 0,
  2269. &hHash))
  2270. {
  2271. SP_LOG_RESULT(GetLastError());
  2272. pctRet = PCT_INT_INTERNAL_ERROR;
  2273. goto error;
  2274. }
  2275. Data.pbData = pbLabel;
  2276. Data.cbData = cbLabel;
  2277. if(!CryptSetHashParam(hHash,
  2278. HP_TLS1PRF_LABEL,
  2279. (PBYTE)&Data,
  2280. 0))
  2281. {
  2282. SP_LOG_RESULT(GetLastError());
  2283. pctRet = PCT_INT_INTERNAL_ERROR;
  2284. goto error;
  2285. }
  2286. Data.pbData = rgbData;
  2287. Data.cbData = cbData;
  2288. if(!CryptSetHashParam(hHash,
  2289. HP_TLS1PRF_SEED,
  2290. (PBYTE)&Data,
  2291. 0))
  2292. {
  2293. SP_LOG_RESULT(GetLastError());
  2294. pctRet = PCT_INT_INTERNAL_ERROR;
  2295. goto error;
  2296. }
  2297. if(!CryptGetHashParam(hHash,
  2298. HP_HASHVAL,
  2299. pbVerifyData,
  2300. &cbVerifyData,
  2301. 0))
  2302. {
  2303. SP_LOG_RESULT(GetLastError());
  2304. pctRet = PCT_INT_INTERNAL_ERROR;
  2305. goto error;
  2306. }
  2307. pctRet = PCT_ERR_OK;
  2308. error:
  2309. if(hHash)
  2310. {
  2311. if(!CryptDestroyHash(hHash))
  2312. {
  2313. SP_LOG_RESULT(GetLastError());
  2314. }
  2315. }
  2316. return pctRet;
  2317. }
  2318. SP_STATUS
  2319. SPBuildTlsAlertMessage(
  2320. PSPContext pContext, // in
  2321. PSPBuffer pCommOutput)
  2322. {
  2323. PBYTE pbMessage = NULL;
  2324. DWORD cbMessage;
  2325. BOOL fAllocated = FALSE;
  2326. SP_STATUS pctRet;
  2327. DWORD cbDataOut;
  2328. SP_BEGIN("SPBuildTlsAlertMessage");
  2329. cbMessage = sizeof(SWRAP) +
  2330. CB_SSL3_ALERT_ONLY +
  2331. SP_MAX_DIGEST_LEN +
  2332. SP_MAX_BLOCKCIPHER_SIZE;
  2333. if(pContext->State != TLS1_STATE_ERROR)
  2334. {
  2335. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  2336. }
  2337. if(pCommOutput->pvBuffer)
  2338. {
  2339. // Application has allocated memory.
  2340. if(pCommOutput->cbBuffer < cbMessage)
  2341. {
  2342. pCommOutput->cbData = cbMessage;
  2343. return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  2344. }
  2345. fAllocated = TRUE;
  2346. }
  2347. else
  2348. {
  2349. // Schannel is to allocate memory.
  2350. pCommOutput->cbBuffer = cbMessage;
  2351. pCommOutput->pvBuffer = SPExternalAlloc(cbMessage);
  2352. if(pCommOutput->pvBuffer == NULL)
  2353. {
  2354. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  2355. }
  2356. }
  2357. pCommOutput->cbData = 0;
  2358. pbMessage = (PBYTE)pCommOutput->pvBuffer;
  2359. // Build alert message.
  2360. BuildAlertMessage(pbMessage,
  2361. pContext->bAlertLevel,
  2362. pContext->bAlertNumber);
  2363. #if DBG
  2364. DBG_HEX_STRING(DEB_TRACE, pbMessage, sizeof(ALRT));
  2365. #endif
  2366. // Build record header and encrypt message.
  2367. pctRet = SPSetWrap(pContext,
  2368. pbMessage,
  2369. SSL3_CT_ALERT,
  2370. CB_SSL3_ALERT_ONLY,
  2371. pContext->dwProtocol & SP_PROT_SSL3TLS1_CLIENTS,
  2372. &cbDataOut);
  2373. if(pctRet != PCT_ERR_OK)
  2374. {
  2375. if(!fAllocated)
  2376. {
  2377. SPExternalFree(pCommOutput->pvBuffer);
  2378. pCommOutput->pvBuffer = NULL;
  2379. }
  2380. SP_RETURN(SP_LOG_RESULT(pctRet));
  2381. }
  2382. // Update buffer length.
  2383. pCommOutput->cbData = cbDataOut;
  2384. SP_ASSERT(pCommOutput->cbData <= pCommOutput->cbBuffer);
  2385. SP_RETURN(PCT_ERR_OK);
  2386. }
  2387. void
  2388. SetTls1Alert(
  2389. PSPContext pContext,
  2390. BYTE bAlertLevel,
  2391. BYTE bAlertNumber)
  2392. {
  2393. pContext->State = TLS1_STATE_ERROR;
  2394. pContext->bAlertLevel = bAlertLevel;
  2395. pContext->bAlertNumber = bAlertNumber;
  2396. }