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.

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