Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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. DWORD dwCapiFlags,
  306. PROV_ENUMALGS_EX ** ppAlgInfo,
  307. DWORD * pcAlgInfo)
  308. {
  309. PROV_ENUMALGS_EX AlgInfo;
  310. DWORD dwFlags;
  311. DWORD cbData;
  312. DWORD cAlgs;
  313. DWORD i;
  314. *ppAlgInfo = NULL;
  315. *pcAlgInfo = 0;
  316. // Count the algorithms.
  317. dwFlags = CRYPT_FIRST;
  318. for(cAlgs = 0; ; cAlgs++)
  319. {
  320. cbData = sizeof(PROV_ENUMALGS_EX);
  321. if(!SchCryptGetProvParam(hProv,
  322. PP_ENUMALGS_EX,
  323. (PBYTE)&AlgInfo,
  324. &cbData,
  325. dwFlags,
  326. dwCapiFlags))
  327. {
  328. if(GetLastError() != ERROR_NO_MORE_ITEMS)
  329. {
  330. SP_LOG_RESULT(GetLastError());
  331. }
  332. break;
  333. }
  334. dwFlags = 0;
  335. }
  336. if(cAlgs == 0)
  337. {
  338. return SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  339. }
  340. // Allocate memory.
  341. *ppAlgInfo = SPExternalAlloc(sizeof(PROV_ENUMALGS_EX) * cAlgs);
  342. if(*ppAlgInfo == NULL)
  343. {
  344. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  345. }
  346. // Read the algorithms.
  347. dwFlags = CRYPT_FIRST;
  348. for(i = 0; i < cAlgs; i++)
  349. {
  350. cbData = sizeof(PROV_ENUMALGS_EX);
  351. if(!SchCryptGetProvParam(hProv,
  352. PP_ENUMALGS_EX,
  353. (PBYTE)(*ppAlgInfo + i),
  354. &cbData,
  355. dwFlags,
  356. dwCapiFlags))
  357. {
  358. if(GetLastError() != ERROR_NO_MORE_ITEMS)
  359. {
  360. SP_LOG_RESULT(GetLastError());
  361. }
  362. break;
  363. }
  364. dwFlags = 0;
  365. }
  366. if(i == 0)
  367. {
  368. SPExternalFree(*ppAlgInfo);
  369. *ppAlgInfo = NULL;
  370. LogNoCiphersSupportedEvent();
  371. return SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  372. }
  373. *pcAlgInfo = i;
  374. return PCT_ERR_OK;
  375. }
  376. SP_STATUS WINAPI
  377. GenerateHello(
  378. PSPContext pContext,
  379. PSPBuffer pOutput,
  380. BOOL fCache)
  381. {
  382. PSessCacheItem pZombie;
  383. PSPCredentialGroup pCred;
  384. BOOL fFound;
  385. DWORD fProt;
  386. if (!pOutput)
  387. {
  388. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  389. }
  390. if(fCache)
  391. {
  392. // Look this id up in the cache
  393. fFound = SPCacheRetrieveByName(pContext->pszTarget,
  394. pContext->pCredGroup,
  395. &pContext->RipeZombie);
  396. }
  397. else
  398. {
  399. fFound = FALSE;
  400. }
  401. if(!fFound)
  402. {
  403. // We're doing a full handshake, so allocate a cache entry.
  404. if(!SPCacheRetrieveNew(FALSE,
  405. pContext->pszTarget,
  406. &pContext->RipeZombie))
  407. {
  408. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  409. }
  410. pContext->RipeZombie->dwCF = pContext->dwRequestedCF;
  411. }
  412. if(pContext->RipeZombie == NULL)
  413. {
  414. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  415. }
  416. pZombie = pContext->RipeZombie;
  417. pCred = pContext->pCredGroup;
  418. if(!pCred)
  419. {
  420. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  421. }
  422. // Use protocol from cache unless it's a new cache element,
  423. // in which case use the protocol from credential.
  424. if(fFound)
  425. {
  426. fProt = pZombie->fProtocol;
  427. }
  428. else
  429. {
  430. fProt = pCred->grbitEnabledProtocols;
  431. }
  432. pContext->dwProtocol = fProt;
  433. pContext->dwClientEnabledProtocols = fProt;
  434. if(SP_PROT_UNI_CLIENT & fProt)
  435. {
  436. pContext->State = UNI_STATE_CLIENT_HELLO;
  437. pContext->ProtocolHandler = ClientProtocolHandler;
  438. return GenerateUniHello(pContext, pOutput, pCred->grbitEnabledProtocols);
  439. }
  440. else
  441. if(SP_PROT_TLS1_CLIENT & fProt)
  442. {
  443. DWORD dwProtocol = SP_PROT_TLS1_CLIENT;
  444. pContext->State = SSL3_STATE_CLIENT_HELLO;
  445. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  446. if(!fFound)
  447. {
  448. pZombie->fProtocol = SP_PROT_TLS1_CLIENT;
  449. }
  450. if(SP_PROT_SSL3_CLIENT & fProt)
  451. {
  452. // Both TLS and SSL3 are enabled.
  453. dwProtocol |= SP_PROT_SSL3_CLIENT;
  454. }
  455. return GenerateTls1ClientHello(pContext, pOutput, dwProtocol);
  456. }
  457. else
  458. if(SP_PROT_SSL3_CLIENT & fProt)
  459. {
  460. pContext->State = SSL3_STATE_CLIENT_HELLO;
  461. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  462. if(!fFound)
  463. {
  464. pZombie->fProtocol = SP_PROT_SSL3_CLIENT;
  465. }
  466. return GenerateSsl3ClientHello(pContext, pOutput);
  467. }
  468. else
  469. if(SP_PROT_PCT1_CLIENT & fProt)
  470. {
  471. pContext->State = PCT1_STATE_CLIENT_HELLO;
  472. pContext->ProtocolHandler = Pct1ClientProtocolHandler;
  473. return GeneratePct1StyleHello(pContext, pOutput);
  474. }
  475. else
  476. if(SP_PROT_SSL2_CLIENT & fProt)
  477. {
  478. pContext->State = SSL2_STATE_CLIENT_HELLO;
  479. pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
  480. return GenerateUniHello(pContext, pOutput, SP_PROT_SSL2_CLIENT);
  481. }
  482. else
  483. {
  484. return SP_LOG_RESULT(SEC_E_ALGORITHM_MISMATCH);
  485. }
  486. }
  487. //+---------------------------------------------------------------------------
  488. //
  489. // Function: ClientVetAlg
  490. //
  491. // Synopsis: Examine the cipher suite input, and decide if it is currently
  492. // enabled. Take into account the enabled protocols and ciphers
  493. // enabled in the schannel registry as well as the protocols and
  494. // ciphers enabled by the application in the V3 credential.
  495. // Return TRUE if the cipher suite is enabled.
  496. //
  497. // Arguments: [pContext] -- Schannel context.
  498. //
  499. // [dwProtocol] -- Client protocols to be included in the
  500. // ClientHello message.
  501. //
  502. // [pCipherMap] -- Cipher suite to be examined.
  503. //
  504. // History: 10-29-97 jbanes Created
  505. //
  506. // Notes: This routine is called by the client-side only.
  507. //
  508. //----------------------------------------------------------------------------
  509. BOOL
  510. ClientVetAlg(
  511. PSPContext pContext,
  512. DWORD dwProtocol,
  513. UNICipherMap * pCipherMap)
  514. {
  515. PCipherInfo pCipherInfo = NULL;
  516. PHashInfo pHashInfo = NULL;
  517. PKeyExchangeInfo pExchInfo = NULL;
  518. if((pCipherMap->fProt & dwProtocol) == 0)
  519. {
  520. return FALSE;
  521. }
  522. // Is cipher supported?
  523. if(pCipherMap->aiCipher != 0)
  524. {
  525. pCipherInfo = GetCipherInfo(pCipherMap->aiCipher,
  526. pCipherMap->dwStrength);
  527. if(!IsCipherSuiteAllowed(pContext,
  528. pCipherInfo,
  529. dwProtocol,
  530. pContext->RipeZombie->dwCF,
  531. pCipherMap->dwFlags))
  532. {
  533. return FALSE;
  534. }
  535. }
  536. // Is hash supported?
  537. if(pCipherMap->aiHash != 0)
  538. {
  539. pHashInfo = GetHashInfo(pCipherMap->aiHash);
  540. if(!IsHashAllowed(pContext, pHashInfo, dwProtocol))
  541. {
  542. return FALSE;
  543. }
  544. }
  545. // Is exchange alg supported?
  546. if(pCipherMap->KeyExch != SP_EXCH_UNKNOWN)
  547. {
  548. pExchInfo = GetKeyExchangeInfo(pCipherMap->KeyExch);
  549. if(!IsExchAllowed(pContext, pExchInfo, dwProtocol))
  550. {
  551. return FALSE;
  552. }
  553. }
  554. return TRUE;
  555. }
  556. //+---------------------------------------------------------------------------
  557. //
  558. // Function: ClientBuildAlgList
  559. //
  560. // Synopsis: Build a list of ciphers to be included in the ClientHello
  561. // message. This routine is used by all protocols.
  562. //
  563. // Arguments: [pContext] -- Schannel context.
  564. //
  565. // [fProtocol] -- Protocol(s) to be included in the
  566. // ClientHello message.
  567. //
  568. // [pCipherSpecs] -- (out) Array where cipher specs are
  569. // placed.
  570. //
  571. // [pcCipherSpecs] -- (out) Size of cipher specs array.
  572. //
  573. // History: 10-29-97 jbanes Created
  574. //
  575. // Notes: This routine is called by the client-side only.
  576. //
  577. //----------------------------------------------------------------------------
  578. SP_STATUS
  579. ClientBuildAlgList(
  580. PSPContext pContext,
  581. DWORD dwProtocol,
  582. Ssl2_Cipher_Kind * pCipherSpecs,
  583. PDWORD pcCipherSpecs)
  584. {
  585. DWORD i;
  586. DWORD cCipherSpecs = 0;
  587. // Consider only the client protocols.
  588. dwProtocol &= SP_PROT_CLIENTS;
  589. //
  590. // Handle the RSA case.
  591. //
  592. if(g_hRsaSchannel && g_pRsaSchannelAlgs)
  593. {
  594. for(i = 0; i < UniNumCiphers; i++)
  595. {
  596. if(UniAvailableCiphers[i].KeyExch != SP_EXCH_RSA_PKCS1 &&
  597. UniAvailableCiphers[i].KeyExch != SP_EXCH_UNKNOWN)
  598. {
  599. continue;
  600. }
  601. if(!ClientVetAlg(pContext, dwProtocol, UniAvailableCiphers + i))
  602. {
  603. continue;
  604. }
  605. if(!IsAlgSupportedCapi(dwProtocol,
  606. UniAvailableCiphers + i,
  607. g_pRsaSchannelAlgs,
  608. g_cRsaSchannelAlgs))
  609. {
  610. continue;
  611. }
  612. // this cipher is good to request
  613. pCipherSpecs[cCipherSpecs++] = UniAvailableCiphers[i].CipherKind;
  614. }
  615. }
  616. //
  617. // Handle the DH case.
  618. //
  619. if(g_hDhSchannelProv)
  620. {
  621. for(i = 0; i < UniNumCiphers; i++)
  622. {
  623. if(UniAvailableCiphers[i].KeyExch != SP_EXCH_DH_PKCS3)
  624. {
  625. continue;
  626. }
  627. if(!ClientVetAlg(pContext, dwProtocol, UniAvailableCiphers + i))
  628. {
  629. continue;
  630. }
  631. if(!IsAlgSupportedCapi(dwProtocol,
  632. UniAvailableCiphers + i,
  633. g_pDhSchannelAlgs,
  634. g_cDhSchannelAlgs))
  635. {
  636. continue;
  637. }
  638. // this cipher is good to request
  639. pCipherSpecs[cCipherSpecs++] = UniAvailableCiphers[i].CipherKind;
  640. }
  641. }
  642. if(cCipherSpecs == 0)
  643. {
  644. return SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH);
  645. }
  646. *pcCipherSpecs = cCipherSpecs;
  647. return PCT_ERR_OK;
  648. }
  649. SP_STATUS WINAPI
  650. GenerateUniHelloMessage(
  651. PSPContext pContext,
  652. Ssl2_Client_Hello * pHelloMessage,
  653. DWORD fProtocol
  654. )
  655. {
  656. SP_STATUS pctRet;
  657. UCHAR bOffset = 2;
  658. SP_BEGIN("GenerateUniHelloMessage");
  659. if(!pHelloMessage)
  660. {
  661. SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
  662. }
  663. pContext->Flags |= CONTEXT_FLAG_CLIENT;
  664. // Generate the cipher list
  665. pHelloMessage->cCipherSpecs = MAX_UNI_CIPHERS;
  666. pctRet = ClientBuildAlgList(pContext,
  667. fProtocol,
  668. pHelloMessage->CipherSpecs,
  669. &pHelloMessage->cCipherSpecs);
  670. if(pctRet != PCT_ERR_OK)
  671. {
  672. SP_RETURN(SP_LOG_RESULT(pctRet));
  673. }
  674. // We're minimally version 2
  675. pHelloMessage->dwVer = SSL2_CLIENT_VERSION;
  676. if(fProtocol & SP_PROT_TLS1_CLIENT)
  677. {
  678. pHelloMessage->dwVer = TLS1_CLIENT_VERSION;
  679. }
  680. else if(fProtocol & SP_PROT_SSL3_CLIENT)
  681. {
  682. pHelloMessage->dwVer = SSL3_CLIENT_VERSION;
  683. }
  684. /* Build the hello message. */
  685. pHelloMessage->cbSessionID = 0;
  686. if (pContext->RipeZombie && pContext->RipeZombie->cbSessionID)
  687. {
  688. KeyExchangeSystem *pKeyExchSys = NULL;
  689. // Get pointer to key exchange system.
  690. pKeyExchSys = KeyExchangeFromSpec(pContext->RipeZombie->SessExchSpec,
  691. pContext->RipeZombie->fProtocol);
  692. if(pKeyExchSys)
  693. {
  694. // Request a reconnect.
  695. CopyMemory(pHelloMessage->SessionID,
  696. pContext->RipeZombie->SessionID,
  697. pContext->RipeZombie->cbSessionID);
  698. pHelloMessage->cbSessionID = pContext->RipeZombie->cbSessionID;
  699. }
  700. else
  701. {
  702. DebugLog((DEB_WARN, "Abstaining from requesting reconnect\n"));
  703. }
  704. }
  705. CopyMemory( pHelloMessage->Challenge,
  706. pContext->pChallenge,
  707. pContext->cbChallenge);
  708. pHelloMessage->cbChallenge = pContext->cbChallenge;
  709. SP_RETURN(PCT_ERR_OK);
  710. }
  711. SP_STATUS WINAPI
  712. GenerateUniHello(
  713. PSPContext pContext,
  714. PSPBuffer pOutput,
  715. DWORD fProtocol
  716. )
  717. {
  718. SP_STATUS pctRet;
  719. Ssl2_Client_Hello HelloMessage;
  720. SP_BEGIN("GenerateUniHello");
  721. GenerateRandomBits( pContext->pChallenge, SSL2_CHALLENGE_SIZE );
  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. SP_STATUS pctRet = 0;
  760. PUCHAR pb;
  761. DWORD dwVersion;
  762. PSPCredentialGroup pCred;
  763. pCred = pContext->pCredGroup;
  764. if(!pCred)
  765. {
  766. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  767. }
  768. /* PCTv1.0 Server Hello starts with
  769. * RECORD_LENGTH_MSB (ignore)
  770. * RECORD_LENGTH_LSB (ignore)
  771. * PCT1_SERVER_HELLO (must be equal)
  772. * SH_PAD
  773. * PCT1_CLIENT_VERSION_MSB (must be pct1)
  774. * PCT1_CLIENT_VERSION_LSB (must be pct1)
  775. *
  776. * ... PCT hello ...
  777. */
  778. /* SSLv2 Hello starts with
  779. * RECORD_LENGTH_MSB (ignore)
  780. * RECORD_LENGTH_LSB (ignore)
  781. * SSL2_SERVER_HELLO (must be equal)
  782. * SESSION_ID_HIT
  783. * CERTIFICATE_TYPE
  784. * SSL2_CLIENT_VERSION_MSB (Must be ssl2)
  785. * SSL2_CLIENT_VERSION_LSB (Must be ssl2)
  786. *
  787. * ... SSLv2 Hello ...
  788. */
  789. /* SSLv3 Type 3 Server Hello starts with
  790. * 0x15 Hex (HANDSHAKE MESSAGE)
  791. * VERSION MSB
  792. * VERSION LSB
  793. * RECORD_LENGTH_MSB (ignore)
  794. * RECORD_LENGTH_LSB (ignore)
  795. * HS TYPE (SERVER_HELLO)
  796. * 3 bytes HS record length
  797. * HS Version
  798. * HS Version
  799. */
  800. // We need at least 12 bytes to determine what we have.
  801. if (pCommInput->cbData < 12)
  802. {
  803. return(PCT_INT_INCOMPLETE_MSG);
  804. }
  805. pb = pCommInput->pvBuffer;
  806. if(pb[0] == SSL3_CT_HANDSHAKE && pb[5] == SSL3_HS_SERVER_HELLO)
  807. {
  808. dwVersion = COMBINEBYTES(pb[9], pb[10]);
  809. if((dwVersion == SSL3_CLIENT_VERSION) &&
  810. (pCred->grbitEnabledProtocols & SP_PROT_SSL3_CLIENT))
  811. {
  812. // This appears to be an SSL3 server_hello.
  813. pContext->dwProtocol = SP_PROT_SSL3_CLIENT;
  814. }
  815. else if((dwVersion == TLS1_CLIENT_VERSION) &&
  816. (pCred->grbitEnabledProtocols & SP_PROT_TLS1_CLIENT))
  817. {
  818. // This appears to be a TLS server_hello.
  819. pContext->dwProtocol = SP_PROT_TLS1_CLIENT;
  820. }
  821. else
  822. {
  823. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  824. }
  825. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  826. pContext->DecryptHandler = Ssl3DecryptHandler;
  827. return(Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput));
  828. }
  829. if(pb[2] == SSL2_MT_SERVER_HELLO)
  830. {
  831. dwVersion = COMBINEBYTES(pb[5], pb[6]);
  832. if(dwVersion == SSL2_CLIENT_VERSION)
  833. {
  834. if(!(SP_PROT_SSL2_CLIENT & pCred->grbitEnabledProtocols))
  835. {
  836. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  837. }
  838. // This appears to be an SSL2 server_hello.
  839. pContext->dwProtocol = SP_PROT_SSL2_CLIENT;
  840. pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
  841. pContext->DecryptHandler = Ssl2DecryptHandler;
  842. return(Ssl2ClientProtocolHandler(pContext, pCommInput, pCommOutput));
  843. }
  844. }
  845. if(pb[2] == PCT1_MSG_SERVER_HELLO)
  846. {
  847. DWORD i;
  848. dwVersion = COMBINEBYTES(pb[4], pb[5]);
  849. if(dwVersion ==PCT_VERSION_1)
  850. {
  851. if(!(SP_PROT_PCT1_CLIENT & pCred->grbitEnabledProtocols))
  852. {
  853. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  854. }
  855. // Convert challenge from 16 byte to 32 byte
  856. for(i=0; i < pContext->cbChallenge; i++)
  857. {
  858. pContext->pChallenge[i + pContext->cbChallenge] = ~pContext->pChallenge[i];
  859. }
  860. pContext->cbChallenge = 2*pContext->cbChallenge;
  861. // This appears to be a PCT server_hello.
  862. pContext->dwProtocol = SP_PROT_PCT1_CLIENT;
  863. pContext->ProtocolHandler = Pct1ClientProtocolHandler;
  864. pContext->DecryptHandler = Pct1DecryptHandler;
  865. return(Pct1ClientProtocolHandler(pContext, pCommInput, pCommOutput));
  866. }
  867. }
  868. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  869. }