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.

991 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: cliprot.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. #include <ssl2msg.h>
  21. #include <ssl3msg.h>
  22. #include <ssl2prot.h>
  23. UNICipherMap UniAvailableCiphers[] = {
  24. // NULL cipher suite
  25. {
  26. // 0
  27. SSL3_NULL_WITH_NULL_NULL
  28. },
  29. // PCT ciphers
  30. {
  31. // 1
  32. UNI_CK_PCT,
  33. SP_PROT_PCT1,
  34. 0,
  35. 0, 0,
  36. SP_EXCH_UNKNOWN
  37. },
  38. {
  39. // 2
  40. SSL_MKFAST(PCT_SSL_CERT_TYPE, MSBOF(PCT1_CERT_X509_CHAIN), LSBOF(PCT1_CERT_X509_CHAIN)),
  41. SP_PROT_PCT1,
  42. 0,
  43. 0, 0,
  44. SP_EXCH_UNKNOWN
  45. },
  46. {
  47. // 3
  48. SSL_MKFAST(PCT_SSL_CERT_TYPE, MSBOF(PCT1_CERT_X509), LSBOF(PCT1_CERT_X509)),
  49. SP_PROT_PCT1,
  50. 0,
  51. 0, 0,
  52. SP_EXCH_UNKNOWN
  53. },
  54. {
  55. // 4
  56. SSL_MKFAST(PCT_SSL_HASH_TYPE, MSBOF(PCT1_HASH_MD5), LSBOF(PCT1_HASH_MD5)),
  57. SP_PROT_PCT1,
  58. CALG_MD5,
  59. 0, 0,
  60. SP_EXCH_UNKNOWN
  61. },
  62. {
  63. // 5
  64. SSL_MKFAST(PCT_SSL_HASH_TYPE, MSBOF(PCT1_HASH_SHA), LSBOF(PCT1_HASH_SHA)),
  65. SP_PROT_PCT1,
  66. CALG_SHA,
  67. 0, 0,
  68. SP_EXCH_UNKNOWN
  69. },
  70. {
  71. // 6
  72. SSL_MKFAST(PCT_SSL_EXCH_TYPE, MSBOF(SP_EXCH_RSA_PKCS1), LSBOF(SP_EXCH_RSA_PKCS1)),
  73. SP_PROT_PCT1,
  74. 0,
  75. 0, 0,
  76. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX
  77. },
  78. // SSL3 Domestic ciphers
  79. {
  80. // 7
  81. SSL3_RSA_WITH_RC4_128_MD5,
  82. SP_PROT_SSL3 | SP_PROT_TLS1,
  83. CALG_MD5 ,
  84. CALG_RC4 ,128 ,
  85. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  86. DOMESTIC_CIPHER_SUITE
  87. },
  88. {
  89. // 8
  90. SSL3_RSA_WITH_RC4_128_SHA,
  91. SP_PROT_SSL3 | SP_PROT_TLS1,
  92. CALG_SHA ,
  93. CALG_RC4 ,128 ,
  94. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  95. DOMESTIC_CIPHER_SUITE
  96. },
  97. {
  98. // 9
  99. SSL3_RSA_WITH_3DES_EDE_CBC_SHA,
  100. SP_PROT_SSL3 | SP_PROT_TLS1,
  101. CALG_SHA,
  102. CALG_3DES ,168 ,
  103. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  104. DOMESTIC_CIPHER_SUITE
  105. },
  106. {
  107. // 10
  108. SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
  109. SP_PROT_SSL3 | SP_PROT_TLS1,
  110. CALG_SHA,
  111. CALG_3DES ,168 ,
  112. SP_EXCH_DH_PKCS3, CALG_DH_EPHEM,
  113. DOMESTIC_CIPHER_SUITE
  114. },
  115. // PCT Domestic ciphers
  116. {
  117. // 12
  118. SSL_MKFAST(PCT_SSL_CIPHER_TYPE_1ST_HALF, MSBOF(PCT1_CIPHER_RC4>>16), LSBOF(PCT1_CIPHER_RC4>>16)),
  119. SP_PROT_PCT1,
  120. 0,
  121. CALG_RC4 ,128 ,
  122. SP_EXCH_UNKNOWN, CALG_RSA_KEYX,
  123. DOMESTIC_CIPHER_SUITE
  124. },
  125. {
  126. // 13
  127. SSL_MKFAST(PCT_SSL_CIPHER_TYPE_2ND_HALF, MSBOF(PCT1_ENC_BITS_128), LSBOF(PCT1_MAC_BITS_128)),
  128. SP_PROT_PCT1,
  129. 0,
  130. CALG_RC4 ,128 ,
  131. SP_EXCH_UNKNOWN, CALG_RSA_KEYX,
  132. DOMESTIC_CIPHER_SUITE
  133. },
  134. // SSL2 Domestic ciphers
  135. {
  136. // 14
  137. SSL_CK_RC4_128_WITH_MD5,
  138. SP_PROT_SSL2 ,
  139. CALG_MD5 ,
  140. CALG_RC4 ,128 ,
  141. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  142. DOMESTIC_CIPHER_SUITE
  143. },
  144. {
  145. // 15
  146. SSL_CK_DES_192_EDE3_CBC_WITH_MD5,
  147. SP_PROT_SSL2 ,
  148. CALG_MD5 ,
  149. CALG_3DES ,168 ,
  150. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  151. DOMESTIC_CIPHER_SUITE
  152. },
  153. {
  154. // 16
  155. SSL_CK_RC2_128_CBC_WITH_MD5,
  156. SP_PROT_SSL2 ,
  157. CALG_MD5 ,
  158. CALG_RC2 ,128 ,
  159. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  160. DOMESTIC_CIPHER_SUITE
  161. },
  162. // SSL3 domestic DES ciphers
  163. {
  164. // 22
  165. SSL3_RSA_WITH_DES_CBC_SHA,
  166. SP_PROT_SSL3 | SP_PROT_TLS1,
  167. CALG_SHA ,
  168. CALG_DES , 56,
  169. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  170. DOMESTIC_CIPHER_SUITE
  171. },
  172. {
  173. // 23
  174. SSL3_DHE_DSS_WITH_DES_CBC_SHA,
  175. SP_PROT_SSL3 | SP_PROT_TLS1,
  176. CALG_SHA ,
  177. CALG_DES , 56 ,
  178. SP_EXCH_DH_PKCS3, CALG_DH_EPHEM,
  179. DOMESTIC_CIPHER_SUITE
  180. },
  181. // SSL2 domestic DES ciphers
  182. {
  183. // 24
  184. SSL_CK_DES_64_CBC_WITH_MD5,
  185. SP_PROT_SSL2,
  186. CALG_MD5 ,
  187. CALG_DES , 56 ,
  188. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  189. DOMESTIC_CIPHER_SUITE
  190. },
  191. // SSL3 56-bit export ciphers
  192. {
  193. // 25
  194. TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
  195. SP_PROT_SSL3 | SP_PROT_TLS1,
  196. CALG_SHA ,
  197. CALG_RC4 ,56 ,
  198. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  199. EXPORT56_CIPHER_SUITE
  200. },
  201. {
  202. // 26
  203. TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
  204. SP_PROT_SSL3 | SP_PROT_TLS1,
  205. CALG_SHA ,
  206. CALG_DES , 56,
  207. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  208. EXPORT56_CIPHER_SUITE
  209. },
  210. {
  211. // 27
  212. TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA,
  213. SP_PROT_SSL3 | SP_PROT_TLS1,
  214. CALG_SHA ,
  215. CALG_DES , 56 ,
  216. SP_EXCH_DH_PKCS3, CALG_DH_EPHEM,
  217. EXPORT56_CIPHER_SUITE
  218. },
  219. // SSL3 Export ciphers
  220. {
  221. // 28
  222. SSL3_RSA_EXPORT_WITH_RC4_40_MD5,
  223. SP_PROT_SSL3 | SP_PROT_TLS1,
  224. CALG_MD5 ,
  225. CALG_RC4 ,40 ,
  226. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  227. EXPORT40_CIPHER_SUITE
  228. },
  229. {
  230. // 29
  231. SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
  232. SP_PROT_SSL3 | SP_PROT_TLS1,
  233. CALG_MD5 ,
  234. CALG_RC2 ,40 ,
  235. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  236. EXPORT40_CIPHER_SUITE
  237. },
  238. // PCT Export ciphers
  239. {
  240. // 30
  241. SSL_MKFAST(PCT_SSL_CIPHER_TYPE_1ST_HALF, MSBOF(PCT1_CIPHER_RC4>>16), LSBOF(PCT1_CIPHER_RC4>>16)),
  242. SP_PROT_PCT1,
  243. 0,
  244. CALG_RC4 ,40 ,
  245. SP_EXCH_UNKNOWN, CALG_RSA_KEYX,
  246. EXPORT40_CIPHER_SUITE
  247. },
  248. {
  249. // 31
  250. SSL_MKFAST(PCT_SSL_CIPHER_TYPE_2ND_HALF, MSBOF(PCT1_ENC_BITS_40), LSBOF(PCT1_MAC_BITS_128)),
  251. SP_PROT_PCT1,
  252. 0,
  253. CALG_RC4 ,40 ,
  254. SP_EXCH_UNKNOWN, CALG_RSA_KEYX,
  255. EXPORT40_CIPHER_SUITE
  256. },
  257. // SSL2 Export ciphers
  258. {
  259. // 32
  260. SSL_CK_RC4_128_EXPORT40_WITH_MD5,
  261. SP_PROT_SSL2 ,
  262. CALG_MD5 ,
  263. CALG_RC4 ,40 ,
  264. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  265. EXPORT40_CIPHER_SUITE
  266. },
  267. {
  268. // 33
  269. SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,
  270. SP_PROT_SSL2 ,
  271. CALG_MD5 ,
  272. CALG_RC2 ,40 ,
  273. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  274. EXPORT40_CIPHER_SUITE
  275. },
  276. // SSL3 Zero privacy ciphers
  277. {
  278. // 34
  279. SSL3_RSA_WITH_NULL_MD5,
  280. SP_PROT_SSL3 | SP_PROT_TLS1,
  281. CALG_MD5 ,
  282. CALG_NULLCIPHER, 0,
  283. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  284. DOMESTIC_CIPHER_SUITE
  285. },
  286. {
  287. // 35
  288. SSL3_RSA_WITH_NULL_SHA,
  289. SP_PROT_SSL3 | SP_PROT_TLS1,
  290. CALG_SHA ,
  291. CALG_NULLCIPHER, 0,
  292. SP_EXCH_RSA_PKCS1, CALG_RSA_KEYX,
  293. DOMESTIC_CIPHER_SUITE
  294. }
  295. };
  296. DWORD UniNumCiphers = sizeof(UniAvailableCiphers)/sizeof(UNICipherMap);
  297. SP_STATUS WINAPI
  298. GenerateSsl2StyleHello(
  299. PSPContext pContext,
  300. PSPBuffer pOutput,
  301. WORD fProtocol);
  302. SP_STATUS
  303. GetSupportedCapiAlgs(
  304. HCRYPTPROV hProv,
  305. PROV_ENUMALGS_EX ** ppAlgInfo,
  306. DWORD * pcAlgInfo)
  307. {
  308. PROV_ENUMALGS_EX AlgInfo;
  309. DWORD dwFlags;
  310. DWORD cbData;
  311. DWORD cAlgs;
  312. DWORD i;
  313. *ppAlgInfo = NULL;
  314. *pcAlgInfo = 0;
  315. // Count the algorithms.
  316. dwFlags = CRYPT_FIRST;
  317. for(cAlgs = 0; ; cAlgs++)
  318. {
  319. cbData = sizeof(PROV_ENUMALGS_EX);
  320. if(!CryptGetProvParam(hProv,
  321. PP_ENUMALGS_EX,
  322. (PBYTE)&AlgInfo,
  323. &cbData,
  324. dwFlags))
  325. {
  326. if(GetLastError() != ERROR_NO_MORE_ITEMS)
  327. {
  328. SP_LOG_RESULT(GetLastError());
  329. }
  330. break;
  331. }
  332. dwFlags = 0;
  333. }
  334. if(cAlgs == 0)
  335. {
  336. return SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  337. }
  338. // Allocate memory.
  339. *ppAlgInfo = SPExternalAlloc(sizeof(PROV_ENUMALGS_EX) * cAlgs);
  340. if(*ppAlgInfo == NULL)
  341. {
  342. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  343. }
  344. // Read the algorithms.
  345. dwFlags = CRYPT_FIRST;
  346. for(i = 0; i < cAlgs; i++)
  347. {
  348. cbData = sizeof(PROV_ENUMALGS_EX);
  349. if(!CryptGetProvParam(hProv,
  350. PP_ENUMALGS_EX,
  351. (PBYTE)(*ppAlgInfo + i),
  352. &cbData,
  353. dwFlags))
  354. {
  355. if(GetLastError() != ERROR_NO_MORE_ITEMS)
  356. {
  357. SP_LOG_RESULT(GetLastError());
  358. }
  359. break;
  360. }
  361. dwFlags = 0;
  362. }
  363. if(i == 0)
  364. {
  365. SPExternalFree(*ppAlgInfo);
  366. *ppAlgInfo = NULL;
  367. LogNoCiphersSupportedEvent();
  368. return SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  369. }
  370. *pcAlgInfo = i;
  371. return PCT_ERR_OK;
  372. }
  373. SP_STATUS WINAPI
  374. GenerateHello(
  375. PSPContext pContext,
  376. PSPBuffer pOutput,
  377. BOOL fCache)
  378. {
  379. PSessCacheItem pZombie;
  380. PSPCredentialGroup pCred;
  381. BOOL fFound;
  382. DWORD fProt;
  383. if (!pOutput)
  384. {
  385. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  386. }
  387. if(fCache)
  388. {
  389. // Look this id up in the cache
  390. fFound = SPCacheRetrieveByName(pContext->pszTarget,
  391. pContext->pCredGroup,
  392. &pContext->RipeZombie);
  393. }
  394. else
  395. {
  396. fFound = FALSE;
  397. }
  398. if(!fFound)
  399. {
  400. // We're doing a full handshake, so allocate a cache entry.
  401. if(!SPCacheRetrieveNew(FALSE,
  402. pContext->pszTarget,
  403. &pContext->RipeZombie))
  404. {
  405. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  406. }
  407. pContext->RipeZombie->dwCF = pContext->dwRequestedCF;
  408. }
  409. if(pContext->RipeZombie == NULL)
  410. {
  411. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  412. }
  413. pZombie = pContext->RipeZombie;
  414. pCred = pContext->pCredGroup;
  415. if(!pCred)
  416. {
  417. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  418. }
  419. // Use protocol from cache unless it's a new cache element,
  420. // in which case use the protocol from credential.
  421. if(fFound)
  422. {
  423. fProt = pZombie->fProtocol;
  424. }
  425. else
  426. {
  427. fProt = pCred->grbitEnabledProtocols;
  428. }
  429. pContext->dwProtocol = fProt;
  430. pContext->dwClientEnabledProtocols = fProt;
  431. if(SP_PROT_UNI_CLIENT & fProt)
  432. {
  433. pContext->State = UNI_STATE_CLIENT_HELLO;
  434. pContext->ProtocolHandler = ClientProtocolHandler;
  435. return GenerateUniHello(pContext, pOutput, pCred->grbitEnabledProtocols);
  436. }
  437. else
  438. if(SP_PROT_TLS1_CLIENT & fProt)
  439. {
  440. DWORD dwProtocol = SP_PROT_TLS1_CLIENT;
  441. pContext->State = SSL3_STATE_CLIENT_HELLO;
  442. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  443. if(!fFound)
  444. {
  445. pZombie->fProtocol = SP_PROT_TLS1_CLIENT;
  446. }
  447. if(SP_PROT_SSL3_CLIENT & fProt)
  448. {
  449. // Both TLS and SSL3 are enabled.
  450. dwProtocol |= SP_PROT_SSL3_CLIENT;
  451. }
  452. return GenerateTls1ClientHello(pContext, pOutput, dwProtocol);
  453. }
  454. else
  455. if(SP_PROT_SSL3_CLIENT & fProt)
  456. {
  457. pContext->State = SSL3_STATE_CLIENT_HELLO;
  458. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  459. if(!fFound)
  460. {
  461. pZombie->fProtocol = SP_PROT_SSL3_CLIENT;
  462. }
  463. return GenerateSsl3ClientHello(pContext, pOutput);
  464. }
  465. else
  466. if(SP_PROT_PCT1_CLIENT & fProt)
  467. {
  468. pContext->State = PCT1_STATE_CLIENT_HELLO;
  469. pContext->ProtocolHandler = Pct1ClientProtocolHandler;
  470. return GeneratePct1StyleHello(pContext, pOutput);
  471. }
  472. else
  473. if(SP_PROT_SSL2_CLIENT & fProt)
  474. {
  475. pContext->State = SSL2_STATE_CLIENT_HELLO;
  476. pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
  477. return GenerateUniHello(pContext, pOutput, SP_PROT_SSL2_CLIENT);
  478. }
  479. else
  480. {
  481. return SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  482. }
  483. }
  484. //+---------------------------------------------------------------------------
  485. //
  486. // Function: ClientVetAlg
  487. //
  488. // Synopsis: Examine the cipher suite input, and decide if it is currently
  489. // enabled. Take into account the enabled protocols and ciphers
  490. // enabled in the schannel registry as well as the protocols and
  491. // ciphers enabled by the application in the V3 credential.
  492. // Return TRUE if the cipher suite is enabled.
  493. //
  494. // Arguments: [pContext] -- Schannel context.
  495. //
  496. // [dwProtocol] -- Client protocols to be included in the
  497. // ClientHello message.
  498. //
  499. // [pCipherMap] -- Cipher suite to be examined.
  500. //
  501. // History: 10-29-97 jbanes Created
  502. //
  503. // Notes: This routine is called by the client-side only.
  504. //
  505. //----------------------------------------------------------------------------
  506. BOOL
  507. ClientVetAlg(
  508. PSPContext pContext,
  509. DWORD dwProtocol,
  510. UNICipherMap * pCipherMap)
  511. {
  512. PCipherInfo pCipherInfo = NULL;
  513. PHashInfo pHashInfo = NULL;
  514. PKeyExchangeInfo pExchInfo = NULL;
  515. if((pCipherMap->fProt & dwProtocol) == 0)
  516. {
  517. return FALSE;
  518. }
  519. // Is cipher supported?
  520. if(pCipherMap->aiCipher != 0)
  521. {
  522. pCipherInfo = GetCipherInfo(pCipherMap->aiCipher,
  523. pCipherMap->dwStrength);
  524. if(!IsCipherSuiteAllowed(pContext,
  525. pCipherInfo,
  526. dwProtocol,
  527. pContext->RipeZombie->dwCF,
  528. pCipherMap->dwFlags))
  529. {
  530. return FALSE;
  531. }
  532. }
  533. // Is hash supported?
  534. if(pCipherMap->aiHash != 0)
  535. {
  536. pHashInfo = GetHashInfo(pCipherMap->aiHash);
  537. if(!IsHashAllowed(pContext, pHashInfo, dwProtocol))
  538. {
  539. return FALSE;
  540. }
  541. }
  542. // Is exchange alg supported?
  543. if(pCipherMap->KeyExch != SP_EXCH_UNKNOWN)
  544. {
  545. pExchInfo = GetKeyExchangeInfo(pCipherMap->KeyExch);
  546. if(!IsExchAllowed(pContext, pExchInfo, dwProtocol))
  547. {
  548. return FALSE;
  549. }
  550. }
  551. return TRUE;
  552. }
  553. //+---------------------------------------------------------------------------
  554. //
  555. // Function: ClientBuildAlgList
  556. //
  557. // Synopsis: Build a list of ciphers to be included in the ClientHello
  558. // message. This routine is used by all protocols.
  559. //
  560. // Arguments: [pContext] -- Schannel context.
  561. //
  562. // [fProtocol] -- Protocol(s) to be included in the
  563. // ClientHello message.
  564. //
  565. // [pCipherSpecs] -- (out) Array where cipher specs are
  566. // placed.
  567. //
  568. // [pcCipherSpecs] -- (out) Size of cipher specs array.
  569. //
  570. // History: 10-29-97 jbanes Created
  571. //
  572. // Notes: This routine is called by the client-side only.
  573. //
  574. //----------------------------------------------------------------------------
  575. SP_STATUS
  576. ClientBuildAlgList(
  577. PSPContext pContext,
  578. DWORD dwProtocol,
  579. Ssl2_Cipher_Kind * pCipherSpecs,
  580. PDWORD pcCipherSpecs)
  581. {
  582. DWORD i;
  583. DWORD cCipherSpecs = 0;
  584. // Consider only the client protocols.
  585. dwProtocol &= SP_PROT_CLIENTS;
  586. //
  587. // Handle the RSA case.
  588. //
  589. if(g_hRsaSchannel && g_pRsaSchannelAlgs)
  590. {
  591. for(i = 0; i < UniNumCiphers; i++)
  592. {
  593. if(UniAvailableCiphers[i].KeyExch != SP_EXCH_RSA_PKCS1 &&
  594. UniAvailableCiphers[i].KeyExch != SP_EXCH_UNKNOWN)
  595. {
  596. continue;
  597. }
  598. if(!ClientVetAlg(pContext, dwProtocol, UniAvailableCiphers + i))
  599. {
  600. continue;
  601. }
  602. if(!IsAlgSupportedCapi(dwProtocol,
  603. UniAvailableCiphers + i,
  604. g_pRsaSchannelAlgs,
  605. g_cRsaSchannelAlgs))
  606. {
  607. continue;
  608. }
  609. // this cipher is good to request
  610. pCipherSpecs[cCipherSpecs++] = UniAvailableCiphers[i].CipherKind;
  611. }
  612. }
  613. //
  614. // Handle the DH case.
  615. //
  616. if(g_hDhSchannelProv)
  617. {
  618. for(i = 0; i < UniNumCiphers; i++)
  619. {
  620. if(UniAvailableCiphers[i].KeyExch != SP_EXCH_DH_PKCS3)
  621. {
  622. continue;
  623. }
  624. if(!ClientVetAlg(pContext, dwProtocol, UniAvailableCiphers + i))
  625. {
  626. continue;
  627. }
  628. if(!IsAlgSupportedCapi(dwProtocol,
  629. UniAvailableCiphers + i,
  630. g_pDhSchannelAlgs,
  631. g_cDhSchannelAlgs))
  632. {
  633. continue;
  634. }
  635. // this cipher is good to request
  636. pCipherSpecs[cCipherSpecs++] = UniAvailableCiphers[i].CipherKind;
  637. }
  638. }
  639. if(cCipherSpecs == 0)
  640. {
  641. return SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH);
  642. }
  643. *pcCipherSpecs = cCipherSpecs;
  644. return PCT_ERR_OK;
  645. }
  646. SP_STATUS WINAPI
  647. GenerateUniHelloMessage(
  648. PSPContext pContext,
  649. Ssl2_Client_Hello * pHelloMessage,
  650. DWORD fProtocol
  651. )
  652. {
  653. SP_STATUS pctRet;
  654. SP_BEGIN("GenerateUniHelloMessage");
  655. if(!pHelloMessage)
  656. {
  657. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  658. }
  659. pContext->Flags |= CONTEXT_FLAG_CLIENT;
  660. // Generate the cipher list
  661. pHelloMessage->cCipherSpecs = MAX_UNI_CIPHERS;
  662. pctRet = ClientBuildAlgList(pContext,
  663. fProtocol,
  664. pHelloMessage->CipherSpecs,
  665. &pHelloMessage->cCipherSpecs);
  666. if(pctRet != PCT_ERR_OK)
  667. {
  668. SP_RETURN(SP_LOG_RESULT(pctRet));
  669. }
  670. // We're minimally version 2
  671. pHelloMessage->dwVer = SSL2_CLIENT_VERSION;
  672. if(fProtocol & SP_PROT_TLS1_CLIENT)
  673. {
  674. pHelloMessage->dwVer = TLS1_CLIENT_VERSION;
  675. }
  676. else if(fProtocol & SP_PROT_SSL3_CLIENT)
  677. {
  678. pHelloMessage->dwVer = SSL3_CLIENT_VERSION;
  679. }
  680. /* Build the hello message. */
  681. pHelloMessage->cbSessionID = 0;
  682. if (pContext->RipeZombie && pContext->RipeZombie->cbSessionID)
  683. {
  684. KeyExchangeSystem *pKeyExchSys = NULL;
  685. // Get pointer to key exchange system.
  686. pKeyExchSys = KeyExchangeFromSpec(pContext->RipeZombie->SessExchSpec,
  687. pContext->RipeZombie->fProtocol);
  688. if(pKeyExchSys)
  689. {
  690. // Request a reconnect.
  691. CopyMemory(pHelloMessage->SessionID,
  692. pContext->RipeZombie->SessionID,
  693. pContext->RipeZombie->cbSessionID);
  694. pHelloMessage->cbSessionID = pContext->RipeZombie->cbSessionID;
  695. }
  696. else
  697. {
  698. DebugLog((DEB_WARN, "Abstaining from requesting reconnect\n"));
  699. }
  700. }
  701. CopyMemory( pHelloMessage->Challenge,
  702. pContext->pChallenge,
  703. pContext->cbChallenge);
  704. pHelloMessage->cbChallenge = pContext->cbChallenge;
  705. SP_RETURN(PCT_ERR_OK);
  706. }
  707. SP_STATUS WINAPI
  708. GenerateUniHello(
  709. PSPContext pContext,
  710. PSPBuffer pOutput,
  711. DWORD fProtocol
  712. )
  713. {
  714. SP_STATUS pctRet;
  715. Ssl2_Client_Hello HelloMessage;
  716. SP_BEGIN("GenerateUniHello");
  717. pctRet = GenerateRandomBits(pContext->pChallenge, SSL2_CHALLENGE_SIZE);
  718. if(pctRet != STATUS_SUCCESS)
  719. {
  720. SP_RETURN(pctRet);
  721. }
  722. pContext->cbChallenge = SSL2_CHALLENGE_SIZE;
  723. pctRet = GenerateUniHelloMessage(pContext, &HelloMessage, fProtocol);
  724. pContext->ReadCounter = 0;
  725. if(PCT_ERR_OK != pctRet)
  726. {
  727. SP_RETURN(pctRet);
  728. }
  729. if(PCT_ERR_OK != (pctRet = Ssl2PackClientHello(&HelloMessage, pOutput)))
  730. {
  731. SP_RETURN(pctRet);
  732. }
  733. // Save the ClientHello message so we can hash it later, once
  734. // we know what algorithm and CSP we're using.
  735. if(pContext->pClientHello)
  736. {
  737. SPExternalFree(pContext->pClientHello);
  738. }
  739. pContext->pClientHello = SPExternalAlloc(pOutput->cbData);
  740. if(pContext->pClientHello == NULL)
  741. {
  742. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  743. }
  744. CopyMemory(pContext->pClientHello, pOutput->pvBuffer, pOutput->cbData);
  745. pContext->cbClientHello = pOutput->cbData;
  746. pContext->dwClientHelloProtocol = SP_PROT_SSL2_CLIENT;
  747. /* We set this here to tell the protocol engine that we just send a client
  748. * hello, and we're expecting a pct server hello */
  749. pContext->WriteCounter = 1;
  750. pContext->ReadCounter = 0;
  751. SP_RETURN(PCT_ERR_OK);
  752. }
  753. SP_STATUS WINAPI
  754. ClientProtocolHandler(
  755. PSPContext pContext,
  756. PSPBuffer pCommInput,
  757. PSPBuffer pCommOutput)
  758. {
  759. PUCHAR pb;
  760. DWORD dwVersion;
  761. PSPCredentialGroup pCred;
  762. pCred = pContext->pCredGroup;
  763. if(!pCred)
  764. {
  765. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  766. }
  767. /* PCTv1.0 Server Hello starts with
  768. * RECORD_LENGTH_MSB (ignore)
  769. * RECORD_LENGTH_LSB (ignore)
  770. * PCT1_SERVER_HELLO (must be equal)
  771. * SH_PAD
  772. * PCT1_CLIENT_VERSION_MSB (must be pct1)
  773. * PCT1_CLIENT_VERSION_LSB (must be pct1)
  774. *
  775. * ... PCT hello ...
  776. */
  777. /* SSLv2 Hello starts with
  778. * RECORD_LENGTH_MSB (ignore)
  779. * RECORD_LENGTH_LSB (ignore)
  780. * SSL2_SERVER_HELLO (must be equal)
  781. * SESSION_ID_HIT
  782. * CERTIFICATE_TYPE
  783. * SSL2_CLIENT_VERSION_MSB (Must be ssl2)
  784. * SSL2_CLIENT_VERSION_LSB (Must be ssl2)
  785. *
  786. * ... SSLv2 Hello ...
  787. */
  788. /* SSLv3 Type 3 Server Hello starts with
  789. * 0x15 Hex (HANDSHAKE MESSAGE)
  790. * VERSION MSB
  791. * VERSION LSB
  792. * RECORD_LENGTH_MSB (ignore)
  793. * RECORD_LENGTH_LSB (ignore)
  794. * HS TYPE (SERVER_HELLO)
  795. * 3 bytes HS record length
  796. * HS Version
  797. * HS Version
  798. */
  799. // We need at least 12 bytes to determine what we have.
  800. if (pCommInput->cbData < 12)
  801. {
  802. return(PCT_INT_INCOMPLETE_MSG);
  803. }
  804. pb = pCommInput->pvBuffer;
  805. if(pb[0] == SSL3_CT_HANDSHAKE && pb[5] == SSL3_HS_SERVER_HELLO)
  806. {
  807. dwVersion = COMBINEBYTES(pb[9], pb[10]);
  808. if((dwVersion == SSL3_CLIENT_VERSION) &&
  809. (pCred->grbitEnabledProtocols & SP_PROT_SSL3_CLIENT))
  810. {
  811. // This appears to be an SSL3 server_hello.
  812. pContext->dwProtocol = SP_PROT_SSL3_CLIENT;
  813. }
  814. else if((dwVersion == TLS1_CLIENT_VERSION) &&
  815. (pCred->grbitEnabledProtocols & SP_PROT_TLS1_CLIENT))
  816. {
  817. // This appears to be a TLS server_hello.
  818. pContext->dwProtocol = SP_PROT_TLS1_CLIENT;
  819. }
  820. else
  821. {
  822. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  823. }
  824. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  825. pContext->DecryptHandler = Ssl3DecryptHandler;
  826. return(Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput));
  827. }
  828. if(pb[2] == SSL2_MT_SERVER_HELLO)
  829. {
  830. dwVersion = COMBINEBYTES(pb[5], pb[6]);
  831. if(dwVersion == SSL2_CLIENT_VERSION)
  832. {
  833. if(!(SP_PROT_SSL2_CLIENT & pCred->grbitEnabledProtocols))
  834. {
  835. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  836. }
  837. // This appears to be an SSL2 server_hello.
  838. pContext->dwProtocol = SP_PROT_SSL2_CLIENT;
  839. pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
  840. pContext->DecryptHandler = Ssl2DecryptHandler;
  841. return(Ssl2ClientProtocolHandler(pContext, pCommInput, pCommOutput));
  842. }
  843. }
  844. if(pb[2] == PCT1_MSG_SERVER_HELLO)
  845. {
  846. DWORD i;
  847. dwVersion = COMBINEBYTES(pb[4], pb[5]);
  848. if(dwVersion ==PCT_VERSION_1)
  849. {
  850. if(!(SP_PROT_PCT1_CLIENT & pCred->grbitEnabledProtocols))
  851. {
  852. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  853. }
  854. // Convert challenge from 16 byte to 32 byte
  855. for(i=0; i < pContext->cbChallenge; i++)
  856. {
  857. pContext->pChallenge[i + pContext->cbChallenge] = ~pContext->pChallenge[i];
  858. }
  859. pContext->cbChallenge = 2*pContext->cbChallenge;
  860. // This appears to be a PCT server_hello.
  861. pContext->dwProtocol = SP_PROT_PCT1_CLIENT;
  862. pContext->ProtocolHandler = Pct1ClientProtocolHandler;
  863. pContext->DecryptHandler = Pct1DecryptHandler;
  864. return(Pct1ClientProtocolHandler(pContext, pCommInput, pCommOutput));
  865. }
  866. }
  867. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  868. }