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.

826 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: specmap.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 <des.h>
  19. #include <des3.h>
  20. #include <rc2.h>
  21. /* supported cipher type arrays */
  22. CipherInfo g_AvailableCiphers[] = {
  23. {
  24. // 128 bit RC4
  25. SP_PROT_ALL,
  26. SP_PROT_ALL,
  27. TEXT("RC4 128/128"),
  28. CALG_RC4,
  29. 1,
  30. 128,
  31. 16,
  32. 16,
  33. CF_DOMESTIC | CF_SGC,
  34. },
  35. {
  36. // 168 bit Triple DES
  37. SP_PROT_ALL,
  38. SP_PROT_ALL,
  39. TEXT("Triple DES 168/168"),
  40. CALG_3DES,
  41. DES_BLOCKLEN,
  42. 168,
  43. DES3_KEYSIZE,
  44. DES3_KEYSIZE,
  45. CF_DOMESTIC | CF_SGC,
  46. },
  47. {
  48. // 128 bit RC2
  49. SP_PROT_ALL,
  50. SP_PROT_ALL,
  51. TEXT("RC2 128/128"),
  52. CALG_RC2,
  53. RC2_BLOCKLEN,
  54. 128,
  55. 16,
  56. 16,
  57. CF_DOMESTIC | CF_SGC,
  58. },
  59. {
  60. // 56 bit RC4
  61. SP_PROT_SSL3 | SP_PROT_TLS1,
  62. SP_PROT_SSL3 | SP_PROT_TLS1,
  63. TEXT("RC4 56/128"),
  64. CALG_RC4,
  65. 1,
  66. 56,
  67. 16,
  68. 7,
  69. CF_EXPORT,
  70. },
  71. {
  72. // 56 bit DES
  73. SP_PROT_ALL,
  74. SP_PROT_ALL,
  75. TEXT("DES 56/56"),
  76. CALG_DES,
  77. DES_BLOCKLEN,
  78. 56,
  79. DES_KEYSIZE,
  80. DES_KEYSIZE,
  81. CF_EXPORT,
  82. },
  83. {
  84. // 40 bit RC4
  85. SP_PROT_ALL,
  86. SP_PROT_ALL,
  87. TEXT("RC4 40/128"),
  88. CALG_RC4,
  89. 1,
  90. 40,
  91. 16,
  92. 5,
  93. CF_EXPORT,
  94. },
  95. {
  96. // 40 bit RC2
  97. SP_PROT_ALL,
  98. SP_PROT_ALL,
  99. TEXT("RC2 40/128"),
  100. CALG_RC2,
  101. RC2_BLOCKLEN,
  102. 40,
  103. 16,
  104. 5,
  105. CF_EXPORT,
  106. },
  107. {
  108. // No encryption.
  109. SP_PROT_SSL3TLS1,
  110. SP_PROT_SSL3TLS1,
  111. TEXT("NULL"),
  112. CALG_NULLCIPHER,
  113. 1,
  114. 0,
  115. 0,
  116. 1,
  117. CF_EXPORT,
  118. },
  119. };
  120. DWORD g_cAvailableCiphers = sizeof(g_AvailableCiphers)/sizeof(CipherInfo);
  121. HashInfo g_AvailableHashes[] =
  122. {
  123. {
  124. SP_PROT_ALL,
  125. SP_PROT_ALL,
  126. TEXT("MD5"),
  127. CALG_MD5,
  128. CB_MD5_DIGEST_LEN,
  129. },
  130. {
  131. SP_PROT_ALL,
  132. SP_PROT_ALL,
  133. TEXT("SHA"),
  134. CALG_SHA,
  135. CB_SHA_DIGEST_LEN,
  136. }
  137. };
  138. DWORD g_cAvailableHashes = sizeof(g_AvailableHashes)/sizeof(HashInfo);
  139. CertSysInfo g_AvailableCerts[] =
  140. {
  141. {
  142. SP_PROT_ALL,
  143. SP_PROT_ALL,
  144. X509_ASN_ENCODING,
  145. TEXT("X.509")
  146. }
  147. };
  148. DWORD g_cAvailableCerts = sizeof(g_AvailableCerts)/sizeof(CertSysInfo);
  149. SigInfo g_AvailableSigs[] =
  150. {
  151. {
  152. SP_PROT_ALL,
  153. SP_PROT_ALL,
  154. SP_SIG_RSA_MD2,
  155. TEXT("RSA Signed MD2"),
  156. CALG_MD2,
  157. CALG_RSA_SIGN,
  158. },
  159. {
  160. SP_PROT_ALL,
  161. SP_PROT_ALL,
  162. SP_SIG_RSA_MD5,
  163. TEXT("RSA Signed MD5"),
  164. CALG_MD5,
  165. CALG_RSA_SIGN,
  166. },
  167. {
  168. SP_PROT_SSL3TLS1,
  169. SP_PROT_SSL3TLS1,
  170. SP_SIG_RSA_SHAMD5,
  171. TEXT("RSA Signed MD5/SHA combination"),
  172. (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5), // CALG_SSL3_SHAMD5
  173. CALG_RSA_SIGN,
  174. }
  175. };
  176. DWORD g_cAvailableSigs = sizeof(g_AvailableSigs)/sizeof(SigInfo);
  177. KeyExchangeInfo g_AvailableExch[] =
  178. {
  179. {
  180. CALG_RSA_SIGN,
  181. SP_PROT_ALL,
  182. SP_PROT_ALL,
  183. SP_EXCH_RSA_PKCS1,
  184. TEXT("PKCS"),
  185. &keyexchPKCS
  186. },
  187. {
  188. CALG_RSA_KEYX,
  189. SP_PROT_ALL,
  190. SP_PROT_ALL,
  191. SP_EXCH_RSA_PKCS1,
  192. TEXT("PKCS"),
  193. &keyexchPKCS
  194. },
  195. {
  196. CALG_DH_EPHEM,
  197. SP_PROT_SSL3 | SP_PROT_TLS1,
  198. SP_PROT_SSL3 | SP_PROT_TLS1,
  199. SP_EXCH_DH_PKCS3,
  200. TEXT("Diffie-Hellman"),
  201. &keyexchDH
  202. },
  203. };
  204. DWORD g_cAvailableExch = sizeof(g_AvailableExch)/sizeof(KeyExchangeInfo);
  205. PCipherInfo GetCipherInfo(ALG_ID aiCipher, DWORD dwStrength)
  206. {
  207. DWORD i;
  208. for (i = 0; i < g_cAvailableCiphers; i++ )
  209. {
  210. if(g_AvailableCiphers[i].aiCipher == aiCipher &&
  211. g_AvailableCiphers[i].dwStrength == dwStrength)
  212. {
  213. return &g_AvailableCiphers[i];
  214. }
  215. }
  216. return NULL;
  217. }
  218. PHashInfo GetHashInfo(ALG_ID aiHash)
  219. {
  220. DWORD i;
  221. for (i = 0; i < g_cAvailableHashes; i++ )
  222. {
  223. if(g_AvailableHashes[i].aiHash == aiHash)
  224. {
  225. return &g_AvailableHashes[i];
  226. }
  227. }
  228. return NULL;
  229. }
  230. PKeyExchangeInfo GetKeyExchangeInfo(ExchSpec Spec)
  231. {
  232. DWORD i;
  233. for (i = 0; i < g_cAvailableExch; i++ )
  234. {
  235. if(g_AvailableExch[i].Spec == Spec)
  236. {
  237. return &g_AvailableExch[i];
  238. }
  239. }
  240. return NULL;
  241. }
  242. PKeyExchangeInfo GetKeyExchangeInfoByAlg(ALG_ID aiExch)
  243. {
  244. DWORD i;
  245. for (i = 0; i < g_cAvailableExch; i++ )
  246. {
  247. if(g_AvailableExch[i].aiExch == aiExch)
  248. {
  249. return &g_AvailableExch[i];
  250. }
  251. }
  252. return NULL;
  253. }
  254. PCertSysInfo GetCertSysInfo(CertSpec Spec)
  255. {
  256. DWORD i;
  257. for (i = 0; i < g_cAvailableCerts; i++ )
  258. {
  259. if(g_AvailableCerts[i].Spec == Spec)
  260. {
  261. return &g_AvailableCerts[i];
  262. }
  263. }
  264. return NULL;
  265. }
  266. PSigInfo GetSigInfo(SigSpec Spec)
  267. {
  268. DWORD i;
  269. for (i = 0; i < g_cAvailableSigs; i++ )
  270. {
  271. if(g_AvailableSigs[i].Spec == Spec)
  272. {
  273. return &g_AvailableSigs[i];
  274. }
  275. }
  276. return NULL;
  277. }
  278. KeyExchangeSystem *
  279. KeyExchangeFromSpec(ExchSpec Spec, DWORD fProtocol)
  280. {
  281. PKeyExchangeInfo pInfo;
  282. pInfo = GetKeyExchangeInfo(Spec);
  283. if(pInfo == NULL)
  284. {
  285. return NULL;
  286. }
  287. if(pInfo->fProtocol & fProtocol)
  288. {
  289. return pInfo->System;
  290. }
  291. return NULL;
  292. }
  293. BOOL GetBaseCipherSizes(DWORD *dwMin, DWORD *dwMax)
  294. {
  295. DWORD i;
  296. DWORD dwFlags = CF_EXPORT | CF_FASTSGC | CF_SGC;
  297. *dwMin = 1000;
  298. *dwMax = 0;
  299. dwFlags |= CF_DOMESTIC;
  300. for (i = 0; i < g_cAvailableCiphers; i++ )
  301. {
  302. if(g_AvailableCiphers[i].fProtocol)
  303. {
  304. if(g_AvailableCiphers[i].dwFlags & dwFlags)
  305. {
  306. *dwMin = min(g_AvailableCiphers[i].dwStrength, *dwMin);
  307. *dwMax = max(g_AvailableCiphers[i].dwStrength, *dwMax);
  308. }
  309. }
  310. }
  311. return TRUE;
  312. }
  313. void
  314. GetDisplayCipherSizes(
  315. PSPCredentialGroup pCredGroup,
  316. DWORD *dwMin,
  317. DWORD *dwMax)
  318. {
  319. DWORD i;
  320. DWORD dwFlags = CF_EXPORT;
  321. *dwMin = 1000;
  322. *dwMax = 0;
  323. dwFlags |= CF_DOMESTIC;
  324. for (i = 0; i < g_cAvailableCiphers; i++ )
  325. {
  326. if(g_AvailableCiphers[i].fProtocol)
  327. {
  328. if((g_AvailableCiphers[i].dwFlags & dwFlags) &&
  329. (g_AvailableCiphers[i].dwStrength > 0))
  330. {
  331. *dwMin = min(g_AvailableCiphers[i].dwStrength, *dwMin);
  332. *dwMax = max(g_AvailableCiphers[i].dwStrength, *dwMax);
  333. }
  334. }
  335. }
  336. if(pCredGroup)
  337. {
  338. *dwMin = max(pCredGroup->dwMinStrength, *dwMin);
  339. *dwMax = min(pCredGroup->dwMaxStrength, *dwMax);
  340. }
  341. }
  342. BOOL IsCipherAllowed(
  343. PSPContext pContext,
  344. PCipherInfo pCipher,
  345. DWORD dwProtocol,
  346. DWORD dwFlags)
  347. {
  348. PSPCredentialGroup pCred;
  349. pCred = pContext->pCredGroup;
  350. if(!pCred) return FALSE;
  351. if(!pCipher) return FALSE;
  352. if(pCipher->dwStrength < pCred->dwMinStrength)
  353. {
  354. return FALSE;
  355. }
  356. if(pCipher->dwStrength > pCred->dwMaxStrength)
  357. {
  358. return FALSE;
  359. }
  360. if((pCipher->fProtocol & dwProtocol) == 0)
  361. {
  362. return FALSE;
  363. }
  364. if((pCipher->dwFlags & dwFlags) == 0)
  365. {
  366. return FALSE;
  367. }
  368. return IsAlgAllowed(pCred, pCipher->aiCipher);
  369. }
  370. BOOL
  371. IsCipherSuiteAllowed(
  372. PSPContext pContext,
  373. PCipherInfo pCipher,
  374. DWORD dwProtocol,
  375. DWORD dwFlags,
  376. DWORD dwSuiteFlags)
  377. {
  378. UNREFERENCED_PARAMETER( dwSuiteFlags );
  379. if(!IsCipherAllowed(pContext, pCipher, dwProtocol, dwFlags))
  380. {
  381. return FALSE;
  382. }
  383. return TRUE;
  384. }
  385. BOOL IsHashAllowed(
  386. PSPContext pContext,
  387. PHashInfo pHash,
  388. DWORD dwProtocol)
  389. {
  390. PSPCredentialGroup pCred;
  391. pCred = pContext->pCredGroup;
  392. if(!pCred) return FALSE;
  393. if(!pHash) return FALSE;
  394. if((pHash->fProtocol & dwProtocol) == 0)
  395. {
  396. return FALSE;
  397. }
  398. return IsAlgAllowed(pCred, pHash->aiHash);
  399. }
  400. BOOL IsExchAllowed(
  401. PSPContext pContext,
  402. PKeyExchangeInfo pExch,
  403. DWORD dwProtocol)
  404. {
  405. PSPCredentialGroup pCred;
  406. pCred = pContext->pCredGroup;
  407. if(!pCred) return FALSE;
  408. if(!pExch) return FALSE;
  409. if((pExch->fProtocol & dwProtocol) == 0)
  410. {
  411. return FALSE;
  412. }
  413. return IsAlgAllowed(pCred, pExch->aiExch);
  414. }
  415. BOOL IsAlgAllowed(
  416. PSPCredentialGroup pCred,
  417. ALG_ID aiAlg)
  418. {
  419. DWORD i;
  420. if(!pCred) return FALSE;
  421. if(pCred->palgSupportedAlgs == NULL)
  422. {
  423. return FALSE;
  424. }
  425. for(i = 0; i < pCred->cSupportedAlgs; i++)
  426. {
  427. if(pCred->palgSupportedAlgs[i] == CALG_RSA_KEYX ||
  428. pCred->palgSupportedAlgs[i] == CALG_RSA_SIGN)
  429. {
  430. // accept either algid
  431. if(CALG_RSA_KEYX == aiAlg || CALG_RSA_SIGN == aiAlg)
  432. {
  433. return TRUE;
  434. }
  435. }
  436. else
  437. {
  438. if(pCred->palgSupportedAlgs[i] == aiAlg)
  439. {
  440. return TRUE;
  441. }
  442. }
  443. }
  444. return FALSE;
  445. }
  446. BOOL BuildAlgList(
  447. PSPCredentialGroup pCred,
  448. ALG_ID * aalgRequestedAlgs,
  449. DWORD cRequestedAlgs)
  450. {
  451. DWORD i,j;
  452. DWORD dwAlgClass;
  453. BOOL fCipher=FALSE;
  454. BOOL fHash=FALSE;
  455. BOOL fExch=FALSE;
  456. if(!pCred) return FALSE;
  457. dwAlgClass = 0;
  458. // Get a buffer to hold the algs.
  459. pCred->palgSupportedAlgs = (ALG_ID *)SPExternalAlloc(sizeof(ALG_ID) *
  460. (g_cAvailableCiphers +
  461. g_cAvailableHashes +
  462. g_cAvailableExch));
  463. pCred->cSupportedAlgs = 0;
  464. if(pCred->palgSupportedAlgs == NULL)
  465. {
  466. return FALSE;
  467. }
  468. // Get a list of Alg Classes not specified
  469. if(aalgRequestedAlgs != NULL)
  470. {
  471. for(i=0; i < cRequestedAlgs; i++)
  472. {
  473. BOOL fAddAlg = FALSE;
  474. if(GET_ALG_CLASS(aalgRequestedAlgs[i]) == ALG_CLASS_DATA_ENCRYPT)
  475. {
  476. fCipher=TRUE;
  477. for (j = 0; j < g_cAvailableCiphers; j++ )
  478. {
  479. if((g_AvailableCiphers[j].aiCipher == aalgRequestedAlgs[i]) &&
  480. (g_AvailableCiphers[j].dwStrength >= pCred->dwMinStrength) &&
  481. (g_AvailableCiphers[j].dwStrength <= pCred->dwMaxStrength) &&
  482. (g_AvailableCiphers[j].fProtocol & pCred->grbitEnabledProtocols))
  483. {
  484. fAddAlg = TRUE;
  485. break;
  486. }
  487. }
  488. }
  489. else if(GET_ALG_CLASS(aalgRequestedAlgs[i]) == ALG_CLASS_HASH)
  490. {
  491. PHashInfo pHash;
  492. fHash = TRUE;
  493. pHash = GetHashInfo(aalgRequestedAlgs[i]);
  494. if((NULL != pHash) && (pHash->fProtocol & pCred->grbitEnabledProtocols))
  495. {
  496. fAddAlg = TRUE;
  497. }
  498. }
  499. else if(GET_ALG_CLASS(aalgRequestedAlgs[i]) == ALG_CLASS_KEY_EXCHANGE)
  500. {
  501. PKeyExchangeInfo pExch;
  502. fExch = TRUE;
  503. pExch = GetKeyExchangeInfoByAlg(aalgRequestedAlgs[i]);
  504. if((NULL != pExch) && (pExch->fProtocol & pCred->grbitEnabledProtocols))
  505. {
  506. fAddAlg = TRUE;
  507. }
  508. }
  509. if(fAddAlg & !IsAlgAllowed(pCred, aalgRequestedAlgs[i]))
  510. {
  511. pCred->palgSupportedAlgs[pCred->cSupportedAlgs++] = aalgRequestedAlgs[i];
  512. }
  513. }
  514. }
  515. if(!fCipher)
  516. {
  517. // No ciphers were included in our list, so supply the default ones
  518. for (j = 0; j < g_cAvailableCiphers; j++ )
  519. {
  520. if((g_AvailableCiphers[j].dwStrength >= pCred->dwMinStrength) &&
  521. (g_AvailableCiphers[j].dwStrength <= pCred->dwMaxStrength) &&
  522. (g_AvailableCiphers[j].fProtocol & pCred->grbitEnabledProtocols))
  523. {
  524. if(!IsAlgAllowed(pCred, g_AvailableCiphers[j].aiCipher))
  525. {
  526. pCred->palgSupportedAlgs[pCred->cSupportedAlgs++] = g_AvailableCiphers[j].aiCipher;
  527. }
  528. }
  529. }
  530. }
  531. if(!fHash)
  532. {
  533. // No hashes were included in our list, so supply the default ones
  534. for (j = 0; j < g_cAvailableHashes; j++ )
  535. {
  536. if(g_AvailableHashes[j].fProtocol & pCred->grbitEnabledProtocols)
  537. {
  538. if(!IsAlgAllowed(pCred, g_AvailableHashes[j].aiHash))
  539. {
  540. pCred->palgSupportedAlgs[pCred->cSupportedAlgs++] = g_AvailableHashes[j].aiHash;
  541. }
  542. }
  543. }
  544. }
  545. if(!fExch)
  546. {
  547. // No key exchange algs were included in our list, so supply the default ones
  548. for(j = 0; j < g_cAvailableExch; j++ )
  549. {
  550. if(g_AvailableExch[j].fProtocol & pCred->grbitEnabledProtocols)
  551. {
  552. if(!IsAlgAllowed(pCred, g_AvailableExch[j].aiExch))
  553. {
  554. pCred->palgSupportedAlgs[pCred->cSupportedAlgs++] = g_AvailableExch[j].aiExch;
  555. }
  556. }
  557. }
  558. }
  559. return TRUE;
  560. }
  561. static DWORD
  562. ConvertCapiProtocol(DWORD dwCapiProtocol)
  563. {
  564. DWORD dwProtocol = 0;
  565. if(dwCapiProtocol & CRYPT_FLAG_PCT1)
  566. {
  567. dwProtocol |= SP_PROT_PCT1;
  568. }
  569. if(dwCapiProtocol & CRYPT_FLAG_SSL2)
  570. {
  571. dwProtocol |= SP_PROT_SSL2;
  572. }
  573. if(dwCapiProtocol & CRYPT_FLAG_SSL3)
  574. {
  575. dwProtocol |= SP_PROT_SSL3;
  576. }
  577. if(dwCapiProtocol & CRYPT_FLAG_TLS1)
  578. {
  579. dwProtocol |= SP_PROT_TLS1;
  580. }
  581. return dwProtocol;
  582. }
  583. //+---------------------------------------------------------------------------
  584. //
  585. // Function: IsAlgSupportedCapi
  586. //
  587. // Synopsis: Examine the cipher suite input, and determine if this is
  588. // supported by the schannel CSP. Return TRUE if the
  589. // cipher suite is supported.
  590. //
  591. // Arguments: [dwProtocol] -- Protocols to be included in the
  592. // ClientHello message.
  593. //
  594. // [pCipherMap] -- Cipher suite to be examined.
  595. //
  596. // [pCapiAlgs] -- Array of algorithms supported by the
  597. // schannel CSP.
  598. //
  599. // [cCapiAlgs] -- Number of elements in the pCapiAlgs
  600. // array.
  601. //
  602. // History: 10-29-97 jbanes Created
  603. //
  604. // Notes:
  605. //
  606. //----------------------------------------------------------------------------
  607. BOOL
  608. IsAlgSupportedCapi(
  609. DWORD dwProtocol,
  610. UNICipherMap * pCipherMap,
  611. PROV_ENUMALGS_EX * pCapiAlgs,
  612. DWORD cCapiAlgs)
  613. {
  614. BOOL fFound;
  615. DWORD dwCapiProtocol;
  616. DWORD i;
  617. // Is cipher supported?
  618. if(pCipherMap->aiCipher != 0 && pCipherMap->aiCipher != CALG_NULLCIPHER)
  619. {
  620. for(fFound = FALSE, i = 0; i < cCapiAlgs; i++)
  621. {
  622. if(pCipherMap->aiCipher != pCapiAlgs[i].aiAlgid)
  623. {
  624. continue;
  625. }
  626. if(pCipherMap->dwStrength > pCapiAlgs[i].dwMaxLen ||
  627. pCipherMap->dwStrength < pCapiAlgs[i].dwMinLen)
  628. {
  629. continue;
  630. }
  631. dwCapiProtocol = ConvertCapiProtocol(pCapiAlgs[i].dwProtocols);
  632. if((dwCapiProtocol & dwProtocol) == 0)
  633. {
  634. continue;
  635. }
  636. if((dwCapiProtocol & pCipherMap->fProt) == 0)
  637. {
  638. continue;
  639. }
  640. fFound = TRUE;
  641. break;
  642. }
  643. if(!fFound)
  644. {
  645. return FALSE;
  646. }
  647. }
  648. // Is hash supported?
  649. if(pCipherMap->aiHash != 0)
  650. {
  651. for(fFound = FALSE, i = 0; i < cCapiAlgs; i++)
  652. {
  653. if(pCipherMap->aiHash != pCapiAlgs[i].aiAlgid)
  654. {
  655. continue;
  656. }
  657. dwCapiProtocol = ConvertCapiProtocol(pCapiAlgs[i].dwProtocols);
  658. if((dwCapiProtocol & dwProtocol) == 0)
  659. {
  660. continue;
  661. }
  662. if((dwCapiProtocol & pCipherMap->fProt) == 0)
  663. {
  664. continue;
  665. }
  666. fFound = TRUE;
  667. break;
  668. }
  669. if(!fFound)
  670. {
  671. return FALSE;
  672. }
  673. }
  674. // Is exchange alg supported?
  675. if(pCipherMap->KeyExch != SP_EXCH_UNKNOWN)
  676. {
  677. for(fFound = FALSE, i = 0; i < cCapiAlgs; i++)
  678. {
  679. // RSA
  680. if(pCipherMap->KeyExch == SP_EXCH_RSA_PKCS1)
  681. {
  682. if(pCapiAlgs[i].aiAlgid != CALG_RSA_KEYX)
  683. {
  684. continue;
  685. }
  686. }
  687. // DH
  688. else if(pCipherMap->KeyExch == SP_EXCH_DH_PKCS3)
  689. {
  690. if(pCapiAlgs[i].aiAlgid != CALG_DH_EPHEM)
  691. {
  692. continue;
  693. }
  694. }
  695. // Any other key exchange algorithm
  696. else
  697. {
  698. // Not supported.
  699. continue;
  700. }
  701. dwCapiProtocol = ConvertCapiProtocol(pCapiAlgs[i].dwProtocols);
  702. if((dwCapiProtocol & dwProtocol) == 0)
  703. {
  704. continue;
  705. }
  706. if((dwCapiProtocol & pCipherMap->fProt) == 0)
  707. {
  708. continue;
  709. }
  710. fFound = TRUE;
  711. break;
  712. }
  713. if(!fFound)
  714. {
  715. return FALSE;
  716. }
  717. }
  718. return TRUE;
  719. }