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.

1949 lines
58 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: keyxmspk.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. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21. #ifdef __cplusplus
  22. }
  23. #endif
  24. // PROV_RSA_SCHANNEL handle used when building ClientHello messages.
  25. HCRYPTPROV g_hRsaSchannel = 0;
  26. PROV_ENUMALGS_EX * g_pRsaSchannelAlgs = NULL;
  27. DWORD g_cRsaSchannelAlgs = 0;
  28. SP_STATUS
  29. Ssl3ParseServerKeyExchange(
  30. PSPContext pContext,
  31. PBYTE pbMessage,
  32. DWORD cbMessage,
  33. HCRYPTKEY hServerPublic,
  34. HCRYPTKEY *phNewServerPublic);
  35. SP_STATUS
  36. PkcsFinishMasterKey(
  37. PSPContext pContext,
  38. HCRYPTKEY hMasterKey);
  39. SP_STATUS
  40. WINAPI
  41. PkcsGenerateServerExchangeValue(
  42. SPContext * pContext, // in
  43. PUCHAR pServerExchangeValue, // out
  44. DWORD * pcbServerExchangeValue // in/out
  45. );
  46. SP_STATUS
  47. WINAPI
  48. PkcsGenerateClientExchangeValue(
  49. SPContext * pContext, // in
  50. PUCHAR pServerExchangeValue, // in
  51. DWORD cbServerExchangeValue, // in
  52. PUCHAR pClientClearValue, // out
  53. DWORD * pcbClientClearValue, // in/out
  54. PUCHAR pClientExchangeValue, // out
  55. DWORD * pcbClientExchangeValue // in/out
  56. );
  57. SP_STATUS
  58. WINAPI
  59. PkcsGenerateServerMasterKey(
  60. SPContext * pContext, // in
  61. PUCHAR pClientClearValue, // in
  62. DWORD cbClientClearValue, // in
  63. PUCHAR pClientExchangeValue, // in
  64. DWORD cbClientExchangeValue // in
  65. );
  66. KeyExchangeSystem keyexchPKCS = {
  67. SP_EXCH_RSA_PKCS1,
  68. "RSA",
  69. // PkcsPrivateFromBlob,
  70. PkcsGenerateServerExchangeValue,
  71. PkcsGenerateClientExchangeValue,
  72. PkcsGenerateServerMasterKey,
  73. };
  74. VOID
  75. ReverseMemCopy(
  76. PUCHAR Dest,
  77. PUCHAR Source,
  78. ULONG Size)
  79. {
  80. PUCHAR p;
  81. p = Dest + Size - 1;
  82. do
  83. {
  84. *p-- = *Source++;
  85. } while (p >= Dest);
  86. }
  87. SP_STATUS
  88. GenerateSsl3KeyPair(
  89. PSPContext pContext, // in
  90. DWORD dwKeySize, // in
  91. HCRYPTPROV *phEphemeralProv, // out
  92. HCRYPTKEY * phEphemeralKey) // out
  93. {
  94. HCRYPTPROV * phEphemProv;
  95. PCRYPT_KEY_PROV_INFO pProvInfo = NULL;
  96. PSPCredentialGroup pCredGroup;
  97. PSPCredential pCred;
  98. DWORD cbSize;
  99. SP_STATUS pctRet;
  100. pCredGroup = pContext->RipeZombie->pServerCred;
  101. if(pCredGroup == NULL)
  102. {
  103. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  104. }
  105. LockCredential(pCredGroup);
  106. pCred = pContext->RipeZombie->pActiveServerCred;
  107. if(pCred == NULL)
  108. {
  109. pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  110. goto cleanup;
  111. }
  112. if(dwKeySize == 512)
  113. {
  114. phEphemProv = &pCred->hEphem512Prov;
  115. }
  116. else if(dwKeySize == 1024)
  117. {
  118. phEphemProv = &pCred->hEphem1024Prov;
  119. }
  120. else
  121. {
  122. pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  123. goto cleanup;
  124. }
  125. //
  126. // Obtain CSP context.
  127. //
  128. if(*phEphemProv == 0)
  129. {
  130. // Read the certificate context's "key info" property.
  131. if(CertGetCertificateContextProperty(pCred->pCert,
  132. CERT_KEY_PROV_INFO_PROP_ID,
  133. NULL,
  134. &cbSize))
  135. {
  136. pProvInfo = SPExternalAlloc(cbSize);
  137. if(pProvInfo == NULL)
  138. {
  139. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  140. goto cleanup;
  141. }
  142. if(!CertGetCertificateContextProperty(pCred->pCert,
  143. CERT_KEY_PROV_INFO_PROP_ID,
  144. pProvInfo,
  145. &cbSize))
  146. {
  147. DebugLog((SP_LOG_ERROR, "Error 0x%x reading CERT_KEY_PROV_INFO_PROP_ID\n",GetLastError()));
  148. SPExternalFree(pProvInfo);
  149. pProvInfo = NULL;
  150. }
  151. }
  152. // Obtain a "verify only" csp context.
  153. if(pProvInfo)
  154. {
  155. // If the private key belongs to one of the Microsoft PROV_RSA_FULL
  156. // CSPs, then manually divert it to the Microsoft PROV_RSA_SCHANNEL
  157. // CSP. This works because both CSP types use the same private key
  158. // storage scheme.
  159. if(pProvInfo->dwProvType == PROV_RSA_FULL)
  160. {
  161. if(lstrcmpW(pProvInfo->pwszProvName, MS_DEF_PROV_W) == 0 ||
  162. lstrcmpW(pProvInfo->pwszProvName, MS_STRONG_PROV_W) == 0 ||
  163. lstrcmpW(pProvInfo->pwszProvName, MS_ENHANCED_PROV_W) == 0)
  164. {
  165. DebugLog((DEB_WARN, "Force CSP type to PROV_RSA_SCHANNEL.\n"));
  166. pProvInfo->pwszProvName = MS_DEF_RSA_SCHANNEL_PROV_W;
  167. pProvInfo->dwProvType = PROV_RSA_SCHANNEL;
  168. }
  169. }
  170. if(!SchCryptAcquireContextW(phEphemProv,
  171. NULL,
  172. pProvInfo->pwszProvName,
  173. pProvInfo->dwProvType,
  174. CRYPT_VERIFYCONTEXT,
  175. pCred->dwCapiFlags))
  176. {
  177. SP_LOG_RESULT(GetLastError());
  178. pctRet = SEC_E_NO_CREDENTIALS;
  179. goto cleanup;
  180. }
  181. SPExternalFree(pProvInfo);
  182. pProvInfo = NULL;
  183. }
  184. else
  185. {
  186. if(!SchCryptAcquireContextW(phEphemProv,
  187. NULL,
  188. NULL,
  189. PROV_RSA_SCHANNEL,
  190. CRYPT_VERIFYCONTEXT,
  191. pCred->dwCapiFlags))
  192. {
  193. SP_LOG_RESULT(GetLastError());
  194. pctRet = SEC_E_NO_CREDENTIALS;
  195. goto cleanup;
  196. }
  197. }
  198. }
  199. //
  200. // Obtain handle to private key.
  201. //
  202. if(!SchCryptGetUserKey(*phEphemProv,
  203. AT_KEYEXCHANGE,
  204. phEphemeralKey,
  205. pCred->dwCapiFlags))
  206. {
  207. // Key does not exist, so attempt to create one.
  208. DebugLog((DEB_TRACE, "Creating %d-bit ephemeral key.\n", dwKeySize));
  209. if(!SchCryptGenKey(*phEphemProv,
  210. AT_KEYEXCHANGE,
  211. (dwKeySize << 16),
  212. phEphemeralKey,
  213. pCred->dwCapiFlags))
  214. {
  215. DebugLog((DEB_ERROR, "Error 0x%x generating ephemeral key\n", GetLastError()));
  216. pctRet = SEC_E_NO_CREDENTIALS;
  217. goto cleanup;
  218. }
  219. DebugLog((DEB_TRACE, "Ephemeral key created okay.\n"));
  220. }
  221. *phEphemeralProv = *phEphemProv;
  222. pctRet = PCT_ERR_OK;
  223. cleanup:
  224. if(pProvInfo)
  225. {
  226. SPExternalFree(pProvInfo);
  227. }
  228. UnlockCredential(pCredGroup);
  229. return pctRet;
  230. }
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Function: PkcsGenerateServerExchangeValue
  234. //
  235. // Synopsis: Create a ServerKeyExchange message, containing an ephemeral
  236. // RSA key.
  237. //
  238. // Arguments: [pContext] -- Schannel context.
  239. // [pServerExchangeValue] --
  240. // [pcbServerExchangeValue] --
  241. //
  242. // History: 10-09-97 jbanes Added CAPI integration.
  243. //
  244. // Notes: This routine is called by the server-side only.
  245. //
  246. // In the case of SSL3 or TLS, the ServerKeyExchange message
  247. // consists of the following structure, signed with the
  248. // server's private key.
  249. //
  250. // struct {
  251. // opaque rsa_modulus<1..2^16-1>;
  252. // opaque rsa_exponent<1..2^16-1>;
  253. // } Server RSA Params;
  254. //
  255. // This message is only sent when the server's private key
  256. // is greater then 512 bits and an export cipher suite is
  257. // being negotiated.
  258. //
  259. //----------------------------------------------------------------------------
  260. SP_STATUS
  261. WINAPI
  262. PkcsGenerateServerExchangeValue(
  263. PSPContext pContext, // in
  264. PBYTE pServerExchangeValue, // out
  265. DWORD * pcbServerExchangeValue) // in/out
  266. {
  267. PSPCredential pCred;
  268. HCRYPTKEY hServerKey;
  269. HCRYPTPROV hEphemeralProv;
  270. HCRYPTKEY hEphemeralKey;
  271. DWORD cbData;
  272. DWORD cbServerModulus;
  273. PBYTE pbBlob = NULL;
  274. DWORD cbBlob;
  275. BLOBHEADER * pBlobHeader = NULL;
  276. RSAPUBKEY * pRsaPubKey = NULL;
  277. PBYTE pbModulus = NULL;
  278. DWORD cbModulus;
  279. DWORD cbExp;
  280. PBYTE pbMessage = NULL;
  281. DWORD cbSignature;
  282. HCRYPTHASH hHash;
  283. BYTE rgbHashValue[CB_MD5_DIGEST_LEN + CB_SHA_DIGEST_LEN];
  284. UINT i;
  285. SP_STATUS pctRet;
  286. BOOL fImpersonating = FALSE;
  287. UNICipherMap * pCipherSuite;
  288. DWORD cbAllowedKeySize;
  289. pCred = pContext->RipeZombie->pActiveServerCred;
  290. if(pCred == NULL)
  291. {
  292. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  293. }
  294. pContext->fExchKey = FALSE;
  295. if(pContext->RipeZombie->fProtocol == SP_PROT_SSL2_SERVER ||
  296. pContext->RipeZombie->fProtocol == SP_PROT_PCT1_SERVER)
  297. {
  298. // There is no ServerExchangeValue for SSL2 or PCT1
  299. *pcbServerExchangeValue = 0;
  300. return PCT_ERR_OK;
  301. }
  302. if(pContext->RipeZombie->fProtocol != SP_PROT_SSL3_SERVER &&
  303. pContext->RipeZombie->fProtocol != SP_PROT_TLS1_SERVER)
  304. {
  305. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  306. }
  307. //
  308. // Determine if ServerKeyExchange message is necessary.
  309. //
  310. pCipherSuite = &UniAvailableCiphers[pContext->dwPendingCipherSuiteIndex];
  311. if(pCipherSuite->dwFlags & DOMESTIC_CIPHER_SUITE)
  312. {
  313. // Message not necessary.
  314. *pcbServerExchangeValue = 0;
  315. return PCT_ERR_OK;
  316. }
  317. if(pCred->hProv == 0)
  318. {
  319. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  320. }
  321. fImpersonating = SslImpersonateClient();
  322. if(!SchCryptGetUserKey(pCred->hProv,
  323. pCred->dwKeySpec,
  324. &hServerKey,
  325. pContext->RipeZombie->dwCapiFlags))
  326. {
  327. DebugLog((DEB_ERROR, "Error 0x%x obtaining handle to server public key\n",
  328. GetLastError()));
  329. pctRet = PCT_INT_INTERNAL_ERROR;
  330. goto cleanup;
  331. }
  332. cbData = sizeof(DWORD);
  333. if(!SchCryptGetKeyParam(hServerKey,
  334. KP_BLOCKLEN,
  335. (PBYTE)&cbServerModulus,
  336. &cbData,
  337. 0,
  338. pContext->RipeZombie->dwCapiFlags))
  339. {
  340. SP_LOG_RESULT(GetLastError());
  341. SchCryptDestroyKey(hServerKey, pContext->RipeZombie->dwCapiFlags);
  342. pctRet = PCT_INT_INTERNAL_ERROR;
  343. goto cleanup;
  344. }
  345. SchCryptDestroyKey(hServerKey, pContext->RipeZombie->dwCapiFlags);
  346. if(pCipherSuite->dwFlags & EXPORT56_CIPHER_SUITE)
  347. {
  348. cbAllowedKeySize = 1024;
  349. }
  350. else
  351. {
  352. cbAllowedKeySize = 512;
  353. }
  354. if(cbServerModulus <= cbAllowedKeySize)
  355. {
  356. // Message not necessary.
  357. *pcbServerExchangeValue = 0;
  358. pctRet = PCT_ERR_OK;
  359. goto cleanup;
  360. }
  361. // Convert size from bits to bytes.
  362. cbServerModulus /= 8;
  363. pContext->fExchKey = TRUE;
  364. if(fImpersonating)
  365. {
  366. RevertToSelf();
  367. fImpersonating = FALSE;
  368. }
  369. //
  370. // Compute approximate size of ServerKeyExchange message.
  371. //
  372. if(pServerExchangeValue == NULL)
  373. {
  374. *pcbServerExchangeValue =
  375. 2 + cbAllowedKeySize / 8 + // modulus
  376. 2 + sizeof(DWORD) + // exponent
  377. 2 + cbServerModulus; // signature
  378. pctRet = PCT_ERR_OK;
  379. goto cleanup;
  380. }
  381. //
  382. // Get handle to 512-bit ephemeral RSA key. Generate it if
  383. // we haven't already.
  384. //
  385. pctRet = GenerateSsl3KeyPair(pContext,
  386. cbAllowedKeySize,
  387. &hEphemeralProv,
  388. &hEphemeralKey);
  389. if(pctRet != PCT_ERR_OK)
  390. {
  391. SP_LOG_RESULT(pctRet);
  392. goto cleanup;
  393. }
  394. //
  395. // Export ephemeral key.
  396. //
  397. if(!SchCryptExportKey(hEphemeralKey,
  398. 0,
  399. PUBLICKEYBLOB,
  400. 0,
  401. NULL,
  402. &cbBlob,
  403. pContext->RipeZombie->dwCapiFlags))
  404. {
  405. SP_LOG_RESULT(GetLastError());
  406. pctRet = PCT_INT_INTERNAL_ERROR;
  407. goto cleanup;
  408. }
  409. pbBlob = SPExternalAlloc(cbBlob);
  410. if(pbBlob == NULL)
  411. {
  412. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  413. goto cleanup;
  414. }
  415. if(!SchCryptExportKey(hEphemeralKey,
  416. 0,
  417. PUBLICKEYBLOB,
  418. 0,
  419. pbBlob,
  420. &cbBlob,
  421. pContext->RipeZombie->dwCapiFlags))
  422. {
  423. SP_LOG_RESULT(GetLastError());
  424. SPExternalFree(pbBlob);
  425. pctRet = PCT_INT_INTERNAL_ERROR;
  426. goto cleanup;
  427. }
  428. //
  429. // Destroy handle to ephemeral key. Don't release the ephemeral hProv
  430. // though--that's owned by the credential.
  431. SchCryptDestroyKey(hEphemeralKey, pContext->RipeZombie->dwCapiFlags);
  432. //
  433. // Build message from key blob.
  434. //
  435. pBlobHeader = (BLOBHEADER *)pbBlob;
  436. pRsaPubKey = (RSAPUBKEY *)(pBlobHeader + 1);
  437. pbModulus = (BYTE *)(pRsaPubKey + 1);
  438. cbModulus = pRsaPubKey->bitlen / 8;
  439. pbMessage = pServerExchangeValue;
  440. pbMessage[0] = MSBOF(cbModulus);
  441. pbMessage[1] = LSBOF(cbModulus);
  442. pbMessage += 2;
  443. ReverseMemCopy(pbMessage, pbModulus, cbModulus);
  444. pbMessage += cbModulus;
  445. // Don't laugh, this works - pete
  446. cbExp = ((pRsaPubKey->pubexp & 0xff000000) ? 4 :
  447. ((pRsaPubKey->pubexp & 0x00ff0000) ? 3 :
  448. ((pRsaPubKey->pubexp & 0x0000ff00) ? 2 : 1)));
  449. pbMessage[0] = MSBOF(cbExp);
  450. pbMessage[1] = LSBOF(cbExp);
  451. pbMessage += 2;
  452. ReverseMemCopy(pbMessage, (PBYTE)&pRsaPubKey->pubexp, cbExp);
  453. pbMessage += cbExp;
  454. SPExternalFree(pbBlob);
  455. pbBlob = NULL;
  456. fImpersonating = SslImpersonateClient();
  457. // Generate hash values
  458. ComputeServerExchangeHashes(
  459. pContext,
  460. pServerExchangeValue,
  461. (int)(pbMessage - pServerExchangeValue),
  462. rgbHashValue,
  463. rgbHashValue + CB_MD5_DIGEST_LEN);
  464. // Sign hash value.
  465. if(!SchCryptCreateHash(pCred->hProv,
  466. CALG_SSL3_SHAMD5,
  467. 0,
  468. 0,
  469. &hHash,
  470. pContext->RipeZombie->dwCapiFlags))
  471. {
  472. SP_LOG_RESULT(GetLastError());
  473. pctRet = PCT_INT_INTERNAL_ERROR;
  474. goto cleanup;
  475. }
  476. if(!SchCryptSetHashParam(hHash,
  477. HP_HASHVAL,
  478. rgbHashValue,
  479. 0,
  480. pContext->RipeZombie->dwCapiFlags))
  481. {
  482. SP_LOG_RESULT(GetLastError());
  483. pctRet = PCT_INT_INTERNAL_ERROR;
  484. goto cleanup;
  485. }
  486. DebugLog((DEB_TRACE, "Signing server_key_exchange message.\n"));
  487. cbSignature = cbServerModulus;
  488. if(!SchCryptSignHash(hHash,
  489. pCred->dwKeySpec,
  490. NULL,
  491. 0,
  492. pbMessage + 2,
  493. &cbSignature,
  494. pContext->RipeZombie->dwCapiFlags))
  495. {
  496. SP_LOG_RESULT(GetLastError());
  497. pctRet = PCT_INT_INTERNAL_ERROR;
  498. goto cleanup;
  499. }
  500. DebugLog((DEB_TRACE, "Server_key_exchange message signed successfully.\n"));
  501. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  502. pbMessage[0] = MSBOF(cbSignature);
  503. pbMessage[1] = LSBOF(cbSignature);
  504. pbMessage += 2;
  505. // Reverse signature.
  506. for(i = 0; i < cbSignature / 2; i++)
  507. {
  508. BYTE n = pbMessage[i];
  509. pbMessage[i] = pbMessage[cbSignature - i -1];
  510. pbMessage[cbSignature - i -1] = n;
  511. }
  512. pbMessage += cbSignature;
  513. *pcbServerExchangeValue = (DWORD)(pbMessage - pServerExchangeValue);
  514. // Use ephemeral key for the new connection.
  515. pContext->RipeZombie->hMasterProv = hEphemeralProv;
  516. pContext->RipeZombie->dwFlags |= SP_CACHE_FLAG_MASTER_EPHEM;
  517. pctRet = PCT_ERR_OK;
  518. cleanup:
  519. if(fImpersonating)
  520. {
  521. RevertToSelf();
  522. }
  523. return pctRet;
  524. }
  525. SP_STATUS
  526. WINAPI
  527. PkcsGenerateClientExchangeValue(
  528. SPContext * pContext, // in
  529. PUCHAR pServerExchangeValue, // in
  530. DWORD cbServerExchangeValue, // in
  531. PUCHAR pClientClearValue, // out
  532. DWORD * pcbClientClearValue, // in/out
  533. PUCHAR pClientExchangeValue, // out
  534. DWORD * pcbClientExchangeValue) // in/out
  535. {
  536. PSPCredentialGroup pCred;
  537. DWORD cbSecret;
  538. DWORD cbMasterKey;
  539. HCRYPTKEY hServerPublic = 0;
  540. DWORD dwGenFlags = 0;
  541. DWORD dwExportFlags = 0;
  542. SP_STATUS pctRet = PCT_ERR_OK;
  543. BLOBHEADER *pPublicBlob;
  544. DWORD cbPublicBlob;
  545. DWORD cbHeader;
  546. ALG_ID Algid = 0;
  547. DWORD cbData;
  548. DWORD cbEncryptedKey;
  549. DWORD dwEnabledProtocols;
  550. DWORD dwHighestProtocol;
  551. if(pContext->RipeZombie->hMasterProv == 0)
  552. {
  553. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  554. }
  555. pCred = pContext->pCredGroup;
  556. if(pCred == NULL)
  557. {
  558. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  559. }
  560. // We're doing a full handshake.
  561. pContext->Flags |= CONTEXT_FLAG_FULL_HANDSHAKE;
  562. //
  563. // Determine highest supported protocol.
  564. //
  565. dwEnabledProtocols = pContext->dwClientEnabledProtocols;
  566. if(dwEnabledProtocols & SP_PROT_TLS1_CLIENT)
  567. {
  568. dwHighestProtocol = TLS1_CLIENT_VERSION;
  569. }
  570. else if(dwEnabledProtocols & SP_PROT_SSL3_CLIENT)
  571. {
  572. dwHighestProtocol = SSL3_CLIENT_VERSION;
  573. }
  574. else
  575. {
  576. dwHighestProtocol = SSL2_CLIENT_VERSION;
  577. }
  578. // Get key length.
  579. cbSecret = pContext->pPendingCipherInfo->cbSecret;
  580. //
  581. // Import server's public key.
  582. //
  583. pPublicBlob = pContext->RipeZombie->pRemotePublic->pPublic;
  584. cbPublicBlob = pContext->RipeZombie->pRemotePublic->cbPublic;
  585. cbEncryptedKey = sizeof(BLOBHEADER) + sizeof(ALG_ID) + cbPublicBlob;
  586. if(pClientExchangeValue == NULL)
  587. {
  588. *pcbClientExchangeValue = cbEncryptedKey;
  589. pctRet = PCT_ERR_OK;
  590. goto done;
  591. }
  592. if(*pcbClientExchangeValue < cbEncryptedKey)
  593. {
  594. *pcbClientExchangeValue = cbEncryptedKey;
  595. pctRet = SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
  596. goto done;
  597. }
  598. if(!SchCryptImportKey(pContext->RipeZombie->hMasterProv,
  599. (PBYTE)pPublicBlob,
  600. cbPublicBlob,
  601. 0,
  602. 0,
  603. &hServerPublic,
  604. pContext->RipeZombie->dwCapiFlags))
  605. {
  606. SP_LOG_RESULT(GetLastError());
  607. pctRet = PCT_INT_INTERNAL_ERROR;
  608. goto done;
  609. }
  610. //
  611. // Do protocol specific stuff.
  612. //
  613. switch(pContext->RipeZombie->fProtocol)
  614. {
  615. case SP_PROT_PCT1_CLIENT:
  616. Algid = CALG_PCT1_MASTER;
  617. dwGenFlags = CRYPT_EXPORTABLE;
  618. // Generate the clear key value.
  619. if(cbSecret < PCT1_MASTER_KEY_SIZE)
  620. {
  621. pContext->RipeZombie->cbClearKey = PCT1_MASTER_KEY_SIZE - cbSecret;
  622. GenerateRandomBits( pContext->RipeZombie->pClearKey,
  623. pContext->RipeZombie->cbClearKey);
  624. *pcbClientClearValue = pContext->RipeZombie->cbClearKey;
  625. CopyMemory( pClientClearValue,
  626. pContext->RipeZombie->pClearKey,
  627. pContext->RipeZombie->cbClearKey);
  628. }
  629. else
  630. {
  631. *pcbClientClearValue = pContext->RipeZombie->cbClearKey = 0;
  632. }
  633. break;
  634. case SP_PROT_SSL2_CLIENT:
  635. Algid = CALG_SSL2_MASTER;
  636. dwGenFlags = CRYPT_EXPORTABLE;
  637. cbMasterKey = pContext->pPendingCipherInfo->cbKey;
  638. dwGenFlags |= ((cbSecret << 3) << 16);
  639. // Generate the clear key value.
  640. pContext->RipeZombie->cbClearKey = cbMasterKey - cbSecret;
  641. if(pContext->RipeZombie->cbClearKey > 0)
  642. {
  643. GenerateRandomBits(pContext->RipeZombie->pClearKey,
  644. pContext->RipeZombie->cbClearKey);
  645. CopyMemory(pClientClearValue,
  646. pContext->RipeZombie->pClearKey,
  647. pContext->RipeZombie->cbClearKey);
  648. }
  649. *pcbClientClearValue = pContext->RipeZombie->cbClearKey;
  650. if(dwEnabledProtocols & (SP_PROT_SSL3 | SP_PROT_TLS1))
  651. {
  652. // If we're a client doing SSL2, and
  653. // SSL3 is enabled, then for some reason
  654. // the server requested SSL2. Maybe
  655. // A man in the middle changed the server
  656. // version in the server hello to roll
  657. // back. Pad with 8 0x03's so the server
  658. // can detect this.
  659. dwExportFlags = CRYPT_SSL2_FALLBACK;
  660. }
  661. break;
  662. case SP_PROT_TLS1_CLIENT:
  663. Algid = CALG_TLS1_MASTER;
  664. // drop through to SSL3
  665. case SP_PROT_SSL3_CLIENT:
  666. dwGenFlags = CRYPT_EXPORTABLE;
  667. if(0 == Algid)
  668. {
  669. Algid = CALG_SSL3_MASTER;
  670. }
  671. // Generate the clear key value (always empty).
  672. pContext->RipeZombie->cbClearKey = 0;
  673. if(pcbClientClearValue) *pcbClientClearValue = 0;
  674. if(cbServerExchangeValue && pServerExchangeValue)
  675. {
  676. // In ssl3, we look at the server exchange value.
  677. // It may be a 512-bit public key, signed
  678. // by the server public key. In this case, we need to
  679. // use that as our master_secret encryption key.
  680. HCRYPTKEY hNewServerPublic;
  681. pctRet = Ssl3ParseServerKeyExchange(pContext,
  682. pServerExchangeValue,
  683. cbServerExchangeValue,
  684. hServerPublic,
  685. &hNewServerPublic);
  686. if(pctRet != PCT_ERR_OK)
  687. {
  688. goto done;
  689. }
  690. // Destroy public key from certificate.
  691. SchCryptDestroyKey(hServerPublic, pContext->RipeZombie->dwCapiFlags);
  692. // Use public key from ServerKeyExchange instead.
  693. hServerPublic = hNewServerPublic;
  694. }
  695. break;
  696. default:
  697. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  698. }
  699. // Generate the master_secret.
  700. if(!SchCryptGenKey(pContext->RipeZombie->hMasterProv,
  701. Algid,
  702. dwGenFlags,
  703. &pContext->RipeZombie->hMasterKey,
  704. pContext->RipeZombie->dwCapiFlags))
  705. {
  706. SP_LOG_RESULT(GetLastError());
  707. pctRet = PCT_INT_INTERNAL_ERROR;
  708. goto done;
  709. }
  710. #if 1
  711. // This is currently commented out because when connecting to a server running
  712. // an old version of schannel (NT4 SP3 or so), then we will connect using SSL3,
  713. // but the highest supported protocol is 0x0301. This confuses the server and
  714. // it drops the connection.
  715. // Set highest supported protocol. The CSP will place this version number
  716. // in the pre_master_secret.
  717. if(!SchCryptSetKeyParam(pContext->RipeZombie->hMasterKey,
  718. KP_HIGHEST_VERSION,
  719. (PBYTE)&dwHighestProtocol,
  720. 0,
  721. pContext->RipeZombie->dwCapiFlags))
  722. {
  723. SP_LOG_RESULT(GetLastError());
  724. }
  725. #endif
  726. // Encrypt the master_secret.
  727. DebugLog((DEB_TRACE, "Encrypt the master secret.\n"));
  728. if(!SchCryptExportKey(pContext->RipeZombie->hMasterKey,
  729. hServerPublic,
  730. SIMPLEBLOB,
  731. dwExportFlags,
  732. pClientExchangeValue,
  733. &cbEncryptedKey,
  734. pContext->RipeZombie->dwCapiFlags))
  735. {
  736. SP_LOG_RESULT(GetLastError());
  737. pctRet = PCT_INT_INTERNAL_ERROR;
  738. goto done;
  739. }
  740. DebugLog((DEB_TRACE, "Master secret encrypted successfully.\n"));
  741. // Determine size of key exchange key.
  742. cbData = sizeof(DWORD);
  743. if(!SchCryptGetKeyParam(hServerPublic,
  744. KP_BLOCKLEN,
  745. (PBYTE)&pContext->RipeZombie->dwExchStrength,
  746. &cbData,
  747. 0,
  748. pContext->RipeZombie->dwCapiFlags))
  749. {
  750. SP_LOG_RESULT(GetLastError());
  751. pContext->RipeZombie->dwExchStrength = 0;
  752. }
  753. // Strip off the blob header and copy the encrypted master_secret
  754. // to the output buffer. Note that it is also converted to big endian.
  755. cbHeader = sizeof(BLOBHEADER) + sizeof(ALG_ID);
  756. cbEncryptedKey -= cbHeader;
  757. if(pContext->RipeZombie->fProtocol == SP_PROT_TLS1_CLIENT)
  758. {
  759. MoveMemory(pClientExchangeValue + 2, pClientExchangeValue + cbHeader, cbEncryptedKey);
  760. ReverseInPlace(pClientExchangeValue + 2, cbEncryptedKey);
  761. pClientExchangeValue[0] = MSBOF(cbEncryptedKey);
  762. pClientExchangeValue[1] = LSBOF(cbEncryptedKey);
  763. *pcbClientExchangeValue = 2 + cbEncryptedKey;
  764. }
  765. else
  766. {
  767. MoveMemory(pClientExchangeValue, pClientExchangeValue + cbHeader, cbEncryptedKey);
  768. ReverseInPlace(pClientExchangeValue, cbEncryptedKey);
  769. *pcbClientExchangeValue = cbEncryptedKey;
  770. }
  771. // Build the session keys.
  772. pctRet = MakeSessionKeys(pContext,
  773. pContext->RipeZombie->hMasterProv,
  774. pContext->RipeZombie->hMasterKey);
  775. if(pctRet != PCT_ERR_OK)
  776. {
  777. goto done;
  778. }
  779. // Update perf counter.
  780. InterlockedIncrement(&g_cClientHandshakes);
  781. pctRet = PCT_ERR_OK;
  782. done:
  783. if(hServerPublic) SchCryptDestroyKey(hServerPublic, pContext->RipeZombie->dwCapiFlags);
  784. return pctRet;
  785. }
  786. SP_STATUS
  787. GenerateRandomMasterKey(
  788. PSPContext pContext,
  789. HCRYPTKEY * phMasterKey)
  790. {
  791. DWORD dwGenFlags = 0;
  792. ALG_ID Algid = 0;
  793. DWORD cbSecret;
  794. cbSecret = pContext->pPendingCipherInfo->cbSecret;
  795. switch(pContext->RipeZombie->fProtocol)
  796. {
  797. case SP_PROT_PCT1_SERVER:
  798. Algid = CALG_PCT1_MASTER;
  799. dwGenFlags = CRYPT_EXPORTABLE;
  800. break;
  801. case SP_PROT_SSL2_SERVER:
  802. Algid = CALG_SSL2_MASTER;
  803. dwGenFlags = CRYPT_EXPORTABLE;
  804. dwGenFlags |= ((cbSecret << 3) << 16);
  805. break;
  806. case SP_PROT_TLS1_SERVER:
  807. Algid = CALG_TLS1_MASTER;
  808. dwGenFlags = CRYPT_EXPORTABLE;
  809. break;
  810. case SP_PROT_SSL3_SERVER:
  811. Algid = CALG_SSL3_MASTER;
  812. dwGenFlags = CRYPT_EXPORTABLE;
  813. break;
  814. default:
  815. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  816. }
  817. // Generate the master_secret.
  818. if(!SchCryptGenKey(pContext->RipeZombie->hMasterProv,
  819. Algid,
  820. dwGenFlags,
  821. phMasterKey,
  822. pContext->RipeZombie->dwCapiFlags))
  823. {
  824. SP_LOG_RESULT(GetLastError());
  825. return PCT_INT_INTERNAL_ERROR;
  826. }
  827. return PCT_ERR_OK;
  828. }
  829. //+---------------------------------------------------------------------------
  830. //
  831. // Function: PkcsGenerateServerMasterKey
  832. //
  833. // Synopsis: Decrypt the master secret (from the ClientKeyExchange message)
  834. // and derive the session keys from it.
  835. //
  836. // Arguments: [pContext] -- Schannel context.
  837. // [pClientClearValue] -- Not used.
  838. // [cbClientClearValue] -- Not used.
  839. // [pClientExchangeValue] -- Pointer PKCS #2 block.
  840. // [cbClientExchangeValue] -- Length of block.
  841. //
  842. // History: 10-02-97 jbanes Created.
  843. //
  844. // Notes: This routine is called by the server-side only.
  845. //
  846. //----------------------------------------------------------------------------
  847. SP_STATUS
  848. WINAPI
  849. PkcsGenerateServerMasterKey(
  850. PSPContext pContext, // in, out
  851. PUCHAR pClientClearValue, // in
  852. DWORD cbClientClearValue, // in
  853. PUCHAR pClientExchangeValue, // in
  854. DWORD cbClientExchangeValue) // in
  855. {
  856. PSPCredentialGroup pCred;
  857. PBYTE pbBlob = NULL;
  858. DWORD cbBlob;
  859. ALG_ID Algid;
  860. HCRYPTKEY hMasterKey;
  861. HCRYPTKEY hExchKey = 0;
  862. DWORD dwFlags = 0;
  863. SP_STATUS pctRet;
  864. DWORD cbData;
  865. DWORD dwEnabledProtocols;
  866. DWORD dwHighestProtocol;
  867. BOOL fImpersonating = FALSE;
  868. pCred = pContext->RipeZombie->pServerCred;
  869. if(pCred == NULL)
  870. {
  871. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  872. }
  873. dwEnabledProtocols = (g_ProtEnabled & pCred->grbitEnabledProtocols);
  874. if(dwEnabledProtocols & SP_PROT_TLS1_SERVER)
  875. {
  876. dwHighestProtocol = TLS1_CLIENT_VERSION;
  877. }
  878. else if(dwEnabledProtocols & SP_PROT_SSL3_SERVER)
  879. {
  880. dwHighestProtocol = SSL3_CLIENT_VERSION;
  881. }
  882. else
  883. {
  884. dwHighestProtocol = SSL2_CLIENT_VERSION;
  885. }
  886. // We're doing a full handshake.
  887. pContext->Flags |= CONTEXT_FLAG_FULL_HANDSHAKE;
  888. // Determine encryption algid
  889. switch(pContext->RipeZombie->fProtocol)
  890. {
  891. case SP_PROT_PCT1_SERVER:
  892. Algid = CALG_PCT1_MASTER;
  893. CopyMemory(pContext->RipeZombie->pClearKey,
  894. pClientClearValue,
  895. cbClientClearValue);
  896. pContext->RipeZombie->cbClearKey = cbClientClearValue;
  897. break;
  898. case SP_PROT_SSL2_SERVER:
  899. Algid = CALG_SSL2_MASTER;
  900. if(dwEnabledProtocols & (SP_PROT_SSL3 | SP_PROT_TLS1))
  901. {
  902. // We're a server doing SSL2, and we also support SSL3.
  903. // If the encryption block contains the 8 0x03 padding
  904. // bytes, then abort the connection.
  905. dwFlags = CRYPT_SSL2_FALLBACK;
  906. }
  907. CopyMemory(pContext->RipeZombie->pClearKey,
  908. pClientClearValue,
  909. cbClientClearValue);
  910. pContext->RipeZombie->cbClearKey = cbClientClearValue;
  911. break;
  912. case SP_PROT_SSL3_SERVER:
  913. Algid = CALG_SSL3_MASTER;
  914. break;
  915. case SP_PROT_TLS1_SERVER:
  916. Algid = CALG_TLS1_MASTER;
  917. break;
  918. default:
  919. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  920. }
  921. // Remove (pseudo-optional) vector in front of the encrypted master key.
  922. if(pContext->RipeZombie->fProtocol == SP_PROT_SSL3_SERVER ||
  923. pContext->RipeZombie->fProtocol == SP_PROT_TLS1_SERVER)
  924. {
  925. DWORD cbMsg = MAKEWORD(pClientExchangeValue[1], pClientExchangeValue[0]);
  926. if(cbMsg + 2 == cbClientExchangeValue)
  927. {
  928. pClientExchangeValue += 2;
  929. cbClientExchangeValue -= 2;
  930. }
  931. }
  932. // Allocate memory for blob.
  933. cbBlob = sizeof(BLOBHEADER) + sizeof(ALG_ID) + cbClientExchangeValue;
  934. pbBlob = SPExternalAlloc(cbBlob);
  935. if(pbBlob == NULL)
  936. {
  937. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  938. }
  939. // Build SIMPLEBLOB.
  940. {
  941. BLOBHEADER *pBlobHeader = (BLOBHEADER *)pbBlob;
  942. ALG_ID *pAlgid = (ALG_ID *)(pBlobHeader + 1);
  943. BYTE *pData = (BYTE *)(pAlgid + 1);
  944. pBlobHeader->bType = SIMPLEBLOB;
  945. pBlobHeader->bVersion = CUR_BLOB_VERSION;
  946. pBlobHeader->reserved = 0;
  947. pBlobHeader->aiKeyAlg = Algid;
  948. *pAlgid = CALG_RSA_KEYX;
  949. ReverseMemCopy(pData, pClientExchangeValue, cbClientExchangeValue);
  950. }
  951. DebugLog((DEB_TRACE, "Decrypt the master secret.\n"));
  952. if(!(pContext->RipeZombie->dwFlags & SP_CACHE_FLAG_MASTER_EPHEM))
  953. {
  954. fImpersonating = SslImpersonateClient();
  955. }
  956. // Decrypt the master_secret.
  957. if(!SchCryptGetUserKey(pContext->RipeZombie->hMasterProv,
  958. AT_KEYEXCHANGE,
  959. &hExchKey,
  960. pContext->RipeZombie->dwCapiFlags))
  961. {
  962. SP_LOG_RESULT(GetLastError());
  963. pctRet = PCT_INT_INTERNAL_ERROR;
  964. goto cleanup;
  965. }
  966. if(!SchCryptImportKey(pContext->RipeZombie->hMasterProv,
  967. pbBlob,
  968. cbBlob,
  969. hExchKey,
  970. dwFlags,
  971. &hMasterKey,
  972. pContext->RipeZombie->dwCapiFlags))
  973. {
  974. SP_LOG_RESULT(GetLastError());
  975. DebugLog((DEB_TRACE, "Master secret did not decrypt correctly.\n"));
  976. // Guard against the PKCS#1 attack by generating a
  977. // random master key.
  978. pctRet = GenerateRandomMasterKey(pContext, &hMasterKey);
  979. if(pctRet != PCT_ERR_OK)
  980. {
  981. pctRet = PCT_INT_INTERNAL_ERROR;
  982. goto cleanup;
  983. }
  984. }
  985. else
  986. {
  987. DebugLog((DEB_TRACE, "Master secret decrypted successfully.\n"));
  988. // Set highest supported protocol. The CSP will use this to check for
  989. // version fallback attacks.
  990. if(!SchCryptSetKeyParam(hMasterKey,
  991. KP_HIGHEST_VERSION,
  992. (PBYTE)&dwHighestProtocol,
  993. CRYPT_SERVER,
  994. pContext->RipeZombie->dwCapiFlags))
  995. {
  996. SP_LOG_RESULT(GetLastError());
  997. if(GetLastError() == NTE_BAD_VER)
  998. {
  999. pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1000. SchCryptDestroyKey(hMasterKey, pContext->RipeZombie->dwCapiFlags);
  1001. goto cleanup;
  1002. }
  1003. }
  1004. }
  1005. pContext->RipeZombie->hMasterKey = hMasterKey;
  1006. // Determine size of key exchange key.
  1007. cbData = sizeof(DWORD);
  1008. if(!SchCryptGetKeyParam(hExchKey,
  1009. KP_BLOCKLEN,
  1010. (PBYTE)&pContext->RipeZombie->dwExchStrength,
  1011. &cbData,
  1012. 0,
  1013. pContext->RipeZombie->dwCapiFlags))
  1014. {
  1015. SP_LOG_RESULT(GetLastError());
  1016. pContext->RipeZombie->dwExchStrength = 0;
  1017. }
  1018. SchCryptDestroyKey(hExchKey, pContext->RipeZombie->dwCapiFlags);
  1019. hExchKey = 0;
  1020. // Build the session keys.
  1021. pctRet = MakeSessionKeys(pContext,
  1022. pContext->RipeZombie->hMasterProv,
  1023. hMasterKey);
  1024. if(pctRet != PCT_ERR_OK)
  1025. {
  1026. SP_LOG_RESULT(pctRet);
  1027. goto cleanup;
  1028. }
  1029. // Update perf counter.
  1030. InterlockedIncrement(&g_cServerHandshakes);
  1031. pctRet = PCT_ERR_OK;
  1032. cleanup:
  1033. if(fImpersonating)
  1034. {
  1035. RevertToSelf();
  1036. }
  1037. if(pbBlob != NULL)
  1038. {
  1039. SPExternalFree(pbBlob);
  1040. }
  1041. if(hExchKey)
  1042. {
  1043. SchCryptDestroyKey(hExchKey, pContext->RipeZombie->dwCapiFlags);
  1044. }
  1045. return pctRet;
  1046. }
  1047. //+---------------------------------------------------------------------------
  1048. //
  1049. // Function: PkcsFinishMasterKey
  1050. //
  1051. // Synopsis: Complete the derivation of the master key by programming the
  1052. // CSP with the (protocol dependent) auxilary plaintext
  1053. // information.
  1054. //
  1055. // Arguments: [pContext] -- Schannel context.
  1056. // [hMasterKey] -- Handle to master key.
  1057. //
  1058. // History: 10-03-97 jbanes Created.
  1059. //
  1060. // Notes: This routine is called by the server-side only.
  1061. //
  1062. //----------------------------------------------------------------------------
  1063. SP_STATUS
  1064. PkcsFinishMasterKey(
  1065. PSPContext pContext, // in, out
  1066. HCRYPTKEY hMasterKey) // in
  1067. {
  1068. PCipherInfo pCipherInfo = NULL;
  1069. PHashInfo pHashInfo = NULL;
  1070. SCHANNEL_ALG Algorithm;
  1071. BOOL fExportable = TRUE;
  1072. DWORD dwCipherFlags;
  1073. if(pContext->RipeZombie->hMasterProv == 0)
  1074. {
  1075. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1076. }
  1077. // Get pointer to pending cipher system.
  1078. pCipherInfo = pContext->pPendingCipherInfo;
  1079. // Get pointer to pending hash system.
  1080. pHashInfo = pContext->pPendingHashInfo;
  1081. // Determine whether this is an "exportable" cipher.
  1082. if(pContext->dwPendingCipherSuiteIndex)
  1083. {
  1084. // Use cipher suite flags (SSL3 & TLS).
  1085. dwCipherFlags = UniAvailableCiphers[pContext->dwPendingCipherSuiteIndex].dwFlags;
  1086. if(dwCipherFlags & DOMESTIC_CIPHER_SUITE)
  1087. {
  1088. fExportable = FALSE;
  1089. }
  1090. }
  1091. else
  1092. {
  1093. // Use key length (PCT & SSL2).
  1094. if(pCipherInfo->dwStrength > 40)
  1095. {
  1096. fExportable = FALSE;
  1097. }
  1098. }
  1099. // Specify encryption algorithm.
  1100. if(pCipherInfo->aiCipher != CALG_NULLCIPHER)
  1101. {
  1102. ZeroMemory(&Algorithm, sizeof(Algorithm));
  1103. Algorithm.dwUse = SCHANNEL_ENC_KEY;
  1104. Algorithm.Algid = pCipherInfo->aiCipher;
  1105. Algorithm.cBits = pCipherInfo->cbSecret * 8;
  1106. if(fExportable)
  1107. {
  1108. Algorithm.dwFlags = INTERNATIONAL_USAGE;
  1109. }
  1110. if(!SchCryptSetKeyParam(hMasterKey,
  1111. KP_SCHANNEL_ALG,
  1112. (PBYTE)&Algorithm,
  1113. 0,
  1114. pContext->RipeZombie->dwCapiFlags))
  1115. {
  1116. SP_LOG_RESULT(GetLastError());
  1117. return PCT_INT_INTERNAL_ERROR;
  1118. }
  1119. }
  1120. // Specify hash algorithm.
  1121. Algorithm.dwUse = SCHANNEL_MAC_KEY;
  1122. Algorithm.Algid = pHashInfo->aiHash;
  1123. Algorithm.cBits = pHashInfo->cbCheckSum * 8;
  1124. if(!SchCryptSetKeyParam(hMasterKey,
  1125. KP_SCHANNEL_ALG,
  1126. (PBYTE)&Algorithm,
  1127. 0,
  1128. pContext->RipeZombie->dwCapiFlags))
  1129. {
  1130. SP_LOG_RESULT(GetLastError());
  1131. return PCT_INT_INTERNAL_ERROR;
  1132. }
  1133. // Finish creating the master_secret.
  1134. switch(pContext->RipeZombie->fProtocol)
  1135. {
  1136. case SP_PROT_PCT1_CLIENT:
  1137. case SP_PROT_PCT1_SERVER:
  1138. {
  1139. CRYPT_DATA_BLOB Data;
  1140. // Specify clear key value.
  1141. if(pContext->RipeZombie->cbClearKey)
  1142. {
  1143. Data.pbData = pContext->RipeZombie->pClearKey;
  1144. Data.cbData = pContext->RipeZombie->cbClearKey;
  1145. if(!SchCryptSetKeyParam(hMasterKey,
  1146. KP_CLEAR_KEY,
  1147. (BYTE*)&Data,
  1148. 0,
  1149. pContext->RipeZombie->dwCapiFlags))
  1150. {
  1151. SP_LOG_RESULT(GetLastError());
  1152. return PCT_INT_INTERNAL_ERROR;
  1153. }
  1154. }
  1155. // Specify the CH_CHALLENGE_DATA.
  1156. Data.pbData = pContext->pChallenge;
  1157. Data.cbData = pContext->cbChallenge;
  1158. if(!SchCryptSetKeyParam(hMasterKey,
  1159. KP_CLIENT_RANDOM,
  1160. (BYTE*)&Data,
  1161. 0,
  1162. pContext->RipeZombie->dwCapiFlags))
  1163. {
  1164. SP_LOG_RESULT(GetLastError());
  1165. return PCT_INT_INTERNAL_ERROR;
  1166. }
  1167. // Specify the SH_CONNECTION_ID_DATA.
  1168. Data.pbData = pContext->pConnectionID;
  1169. Data.cbData = pContext->cbConnectionID;
  1170. if(!SchCryptSetKeyParam(hMasterKey,
  1171. KP_SERVER_RANDOM,
  1172. (BYTE*)&Data,
  1173. 0,
  1174. pContext->RipeZombie->dwCapiFlags))
  1175. {
  1176. SP_LOG_RESULT(GetLastError());
  1177. return PCT_INT_INTERNAL_ERROR;
  1178. }
  1179. // Specify the SH_CERTIFICATE_DATA.
  1180. Data.pbData = pContext->RipeZombie->pbServerCertificate;
  1181. Data.cbData = pContext->RipeZombie->cbServerCertificate;
  1182. if(!SchCryptSetKeyParam(hMasterKey,
  1183. KP_CERTIFICATE,
  1184. (BYTE*)&Data,
  1185. 0,
  1186. pContext->RipeZombie->dwCapiFlags))
  1187. {
  1188. SP_LOG_RESULT(GetLastError());
  1189. return PCT_INT_INTERNAL_ERROR;
  1190. }
  1191. break;
  1192. }
  1193. case SP_PROT_SSL2_CLIENT:
  1194. case SP_PROT_SSL2_SERVER:
  1195. {
  1196. CRYPT_DATA_BLOB Data;
  1197. // Specify clear key value.
  1198. if(pContext->RipeZombie->cbClearKey)
  1199. {
  1200. Data.pbData = pContext->RipeZombie->pClearKey;
  1201. Data.cbData = pContext->RipeZombie->cbClearKey;
  1202. if(!SchCryptSetKeyParam(hMasterKey,
  1203. KP_CLEAR_KEY,
  1204. (BYTE*)&Data,
  1205. 0,
  1206. pContext->RipeZombie->dwCapiFlags))
  1207. {
  1208. SP_LOG_RESULT(GetLastError());
  1209. return PCT_INT_INTERNAL_ERROR;
  1210. }
  1211. }
  1212. // Specify the CH_CHALLENGE_DATA.
  1213. Data.pbData = pContext->pChallenge;
  1214. Data.cbData = pContext->cbChallenge;
  1215. if(!SchCryptSetKeyParam(hMasterKey,
  1216. KP_CLIENT_RANDOM,
  1217. (BYTE*)&Data,
  1218. 0,
  1219. pContext->RipeZombie->dwCapiFlags))
  1220. {
  1221. SP_LOG_RESULT(GetLastError());
  1222. return PCT_INT_INTERNAL_ERROR;
  1223. }
  1224. // Specify the SH_CONNECTION_ID_DATA.
  1225. Data.pbData = pContext->pConnectionID;
  1226. Data.cbData = pContext->cbConnectionID;
  1227. if(!SchCryptSetKeyParam(hMasterKey,
  1228. KP_SERVER_RANDOM,
  1229. (BYTE*)&Data,
  1230. 0,
  1231. pContext->RipeZombie->dwCapiFlags))
  1232. {
  1233. SP_LOG_RESULT(GetLastError());
  1234. return PCT_INT_INTERNAL_ERROR;
  1235. }
  1236. break;
  1237. }
  1238. case SP_PROT_SSL3_CLIENT:
  1239. case SP_PROT_SSL3_SERVER:
  1240. case SP_PROT_TLS1_CLIENT:
  1241. case SP_PROT_TLS1_SERVER:
  1242. {
  1243. CRYPT_DATA_BLOB Data;
  1244. // Specify client_random.
  1245. Data.pbData = pContext->rgbS3CRandom;
  1246. Data.cbData = CB_SSL3_RANDOM;
  1247. if(!SchCryptSetKeyParam(hMasterKey,
  1248. KP_CLIENT_RANDOM,
  1249. (BYTE*)&Data,
  1250. 0,
  1251. pContext->RipeZombie->dwCapiFlags))
  1252. {
  1253. SP_LOG_RESULT(GetLastError());
  1254. return PCT_INT_INTERNAL_ERROR;
  1255. }
  1256. // Specify server_random.
  1257. Data.pbData = pContext->rgbS3SRandom;
  1258. Data.cbData = CB_SSL3_RANDOM;
  1259. if(!SchCryptSetKeyParam(hMasterKey,
  1260. KP_SERVER_RANDOM,
  1261. (BYTE*)&Data,
  1262. 0,
  1263. pContext->RipeZombie->dwCapiFlags))
  1264. {
  1265. SP_LOG_RESULT(GetLastError());
  1266. return PCT_INT_INTERNAL_ERROR;
  1267. }
  1268. break;
  1269. }
  1270. default:
  1271. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1272. }
  1273. return PCT_ERR_OK;
  1274. }
  1275. //+---------------------------------------------------------------------------
  1276. //
  1277. // Function: MakeSessionKeys
  1278. //
  1279. // Synopsis: Derive the session keys from the completed master key.
  1280. //
  1281. // Arguments: [pContext] -- Schannel context.
  1282. // [hProv] --
  1283. // [hMasterKey] -- Handle to master key.
  1284. //
  1285. // History: 10-03-97 jbanes Created.
  1286. //
  1287. // Notes: This routine is called by the server-side only.
  1288. //
  1289. //----------------------------------------------------------------------------
  1290. SP_STATUS
  1291. MakeSessionKeys(
  1292. PSPContext pContext, // in
  1293. HCRYPTPROV hProv, // in
  1294. HCRYPTKEY hMasterKey) // in
  1295. {
  1296. HCRYPTHASH hMasterHash = 0;
  1297. HCRYPTKEY hLocalMasterKey = 0;
  1298. BOOL fClient;
  1299. SP_STATUS pctRet;
  1300. //
  1301. // Duplicate the master key if we're doing a reconnect handshake. This
  1302. // will allow us to set the client_random and server_random properties
  1303. // on the key without having to worry about different threads
  1304. // interferring with each other.
  1305. //
  1306. if((pContext->Flags & CONTEXT_FLAG_FULL_HANDSHAKE) == 0)
  1307. {
  1308. if(!CryptDuplicateKey(hMasterKey, NULL, 0, &hLocalMasterKey))
  1309. {
  1310. pctRet = SP_LOG_RESULT(GetLastError());
  1311. goto cleanup;
  1312. }
  1313. hMasterKey = hLocalMasterKey;
  1314. }
  1315. // Finish the master_secret.
  1316. pctRet = PkcsFinishMasterKey(pContext, hMasterKey);
  1317. if(pctRet != PCT_ERR_OK)
  1318. {
  1319. SP_LOG_RESULT(pctRet);
  1320. goto cleanup;
  1321. }
  1322. fClient = !(pContext->RipeZombie->fProtocol & SP_PROT_SERVERS);
  1323. // Create the master hash object from the master_secret key.
  1324. if(!SchCryptCreateHash(hProv,
  1325. CALG_SCHANNEL_MASTER_HASH,
  1326. hMasterKey,
  1327. 0,
  1328. &hMasterHash,
  1329. 0))
  1330. {
  1331. pctRet = SP_LOG_RESULT(GetLastError());
  1332. goto cleanup;
  1333. }
  1334. // Derive read key from the master hash object.
  1335. if(pContext->hPendingReadKey)
  1336. {
  1337. SchCryptDestroyKey(pContext->hPendingReadKey, 0);
  1338. pContext->hPendingReadKey = 0;
  1339. }
  1340. if(pContext->pPendingCipherInfo->aiCipher != CALG_NULLCIPHER)
  1341. {
  1342. if(!SchCryptDeriveKey(hProv,
  1343. CALG_SCHANNEL_ENC_KEY,
  1344. hMasterHash,
  1345. CRYPT_EXPORTABLE | (fClient ? CRYPT_SERVER : 0),
  1346. &pContext->hPendingReadKey,
  1347. 0))
  1348. {
  1349. pctRet = SP_LOG_RESULT(GetLastError());
  1350. goto cleanup;
  1351. }
  1352. }
  1353. // Derive write key from the master hash object.
  1354. if(pContext->hPendingWriteKey)
  1355. {
  1356. SchCryptDestroyKey(pContext->hPendingWriteKey, 0);
  1357. pContext->hPendingWriteKey = 0;
  1358. }
  1359. if(pContext->pPendingCipherInfo->aiCipher != CALG_NULLCIPHER)
  1360. {
  1361. if(!SchCryptDeriveKey(hProv,
  1362. CALG_SCHANNEL_ENC_KEY,
  1363. hMasterHash,
  1364. CRYPT_EXPORTABLE | (fClient ? 0 : CRYPT_SERVER),
  1365. &pContext->hPendingWriteKey,
  1366. 0))
  1367. {
  1368. pctRet = SP_LOG_RESULT(GetLastError());
  1369. goto cleanup;
  1370. }
  1371. }
  1372. if((pContext->RipeZombie->fProtocol & SP_PROT_SSL2) ||
  1373. (pContext->RipeZombie->fProtocol & SP_PROT_PCT1))
  1374. {
  1375. // Set the IV on the client and server encryption keys
  1376. if(!SchCryptSetKeyParam(pContext->hPendingReadKey,
  1377. KP_IV,
  1378. pContext->RipeZombie->pKeyArgs,
  1379. 0,
  1380. 0))
  1381. {
  1382. pctRet = SP_LOG_RESULT(GetLastError());
  1383. goto cleanup;
  1384. }
  1385. if(!SchCryptSetKeyParam(pContext->hPendingWriteKey,
  1386. KP_IV,
  1387. pContext->RipeZombie->pKeyArgs,
  1388. 0,
  1389. 0))
  1390. {
  1391. pctRet = SP_LOG_RESULT(GetLastError());
  1392. goto cleanup;
  1393. }
  1394. }
  1395. if(pContext->RipeZombie->fProtocol & SP_PROT_SSL2)
  1396. {
  1397. // SSL 2.0 uses same set of keys for both encryption and MAC.
  1398. pContext->hPendingReadMAC = 0;
  1399. pContext->hPendingWriteMAC = 0;
  1400. }
  1401. else
  1402. {
  1403. // Derive read MAC from the master hash object.
  1404. if(pContext->hPendingReadMAC)
  1405. {
  1406. SchCryptDestroyKey(pContext->hPendingReadMAC, 0);
  1407. }
  1408. if(!SchCryptDeriveKey(hProv,
  1409. CALG_SCHANNEL_MAC_KEY,
  1410. hMasterHash,
  1411. CRYPT_EXPORTABLE | (fClient ? CRYPT_SERVER : 0),
  1412. &pContext->hPendingReadMAC,
  1413. 0))
  1414. {
  1415. pctRet = SP_LOG_RESULT(GetLastError());
  1416. goto cleanup;
  1417. }
  1418. // Derive write MAC from the master hash object.
  1419. if(pContext->hPendingWriteMAC)
  1420. {
  1421. SchCryptDestroyKey(pContext->hPendingWriteMAC, 0);
  1422. }
  1423. if(!SchCryptDeriveKey(hProv,
  1424. CALG_SCHANNEL_MAC_KEY,
  1425. hMasterHash,
  1426. CRYPT_EXPORTABLE | (fClient ? 0 : CRYPT_SERVER),
  1427. &pContext->hPendingWriteMAC,
  1428. 0))
  1429. {
  1430. pctRet = SP_LOG_RESULT(GetLastError());
  1431. goto cleanup;
  1432. }
  1433. }
  1434. pctRet = PCT_ERR_OK;
  1435. cleanup:
  1436. if(hMasterHash)
  1437. {
  1438. SchCryptDestroyHash(hMasterHash, 0);
  1439. }
  1440. if(hLocalMasterKey)
  1441. {
  1442. CryptDestroyKey(hLocalMasterKey);
  1443. }
  1444. return pctRet;
  1445. }
  1446. //+---------------------------------------------------------------------------
  1447. //
  1448. // Function: Ssl3ParseServerKeyExchange
  1449. //
  1450. // Synopsis: Parse the ServerKeyExchange message and import modulus and
  1451. // exponent into a CryptoAPI public key.
  1452. //
  1453. // Arguments: [pContext] -- Schannel context.
  1454. //
  1455. // [pbMessage] -- Pointer to message.
  1456. //
  1457. // [cbMessage] -- Message length.
  1458. //
  1459. // [hServerPublic] -- Handle to public key from server's
  1460. // certificate. This is used to verify
  1461. // the message's signature.
  1462. //
  1463. // [phNewServerPublic] -- (output) Handle to new public key.
  1464. //
  1465. //
  1466. // History: 10-23-97 jbanes Created.
  1467. //
  1468. // Notes: This routine is called by the client-side only.
  1469. //
  1470. // The format of the ServerKeyExchange message is:
  1471. //
  1472. // struct {
  1473. // select (KeyExchangeAlgorithm) {
  1474. // case diffie_hellman:
  1475. // ServerDHParams params;
  1476. // Signature signed_params;
  1477. // case rsa:
  1478. // ServerRSAParams params;
  1479. // Signature signed_params;
  1480. // case fortezza_dms:
  1481. // ServerFortezzaParams params;
  1482. // };
  1483. // } ServerKeyExchange;
  1484. //
  1485. // struct {
  1486. // opaque rsa_modulus<1..2^16-1>;
  1487. // opaque rsa_exponent<1..2^16-1>;
  1488. // } ServerRSAParams;
  1489. //
  1490. //----------------------------------------------------------------------------
  1491. SP_STATUS
  1492. Ssl3ParseServerKeyExchange(
  1493. PSPContext pContext, // in
  1494. PBYTE pbMessage, // in
  1495. DWORD cbMessage, // in
  1496. HCRYPTKEY hServerPublic, // in
  1497. HCRYPTKEY *phNewServerPublic) // out
  1498. {
  1499. PBYTE pbModulus = NULL;
  1500. DWORD cbModulus;
  1501. PBYTE pbExponent = NULL;
  1502. DWORD cbExponent;
  1503. PBYTE pbServerParams = NULL;
  1504. DWORD cbServerParams;
  1505. DWORD dwExponent;
  1506. SP_STATUS pctRet;
  1507. DWORD i;
  1508. if(pbMessage == NULL || cbMessage == 0)
  1509. {
  1510. *phNewServerPublic = 0;
  1511. return PCT_ERR_OK;
  1512. }
  1513. // Mark start of ServerRSAParams structure.
  1514. // This is used to build hash values.
  1515. pbServerParams = pbMessage;
  1516. // Modulus length
  1517. cbModulus = MAKEWORD(pbMessage[1], pbMessage[0]);
  1518. pbMessage += 2;
  1519. // Since the modulus is encoded as an INTEGER, it is padded with a leading
  1520. // zero if its most significant bit is one. Remove this padding, if
  1521. // present.
  1522. if(pbMessage[0] == 0)
  1523. {
  1524. cbModulus -= 1;
  1525. pbMessage += 1;
  1526. }
  1527. if(cbModulus < 512/8 || cbModulus > 1024/8)
  1528. {
  1529. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  1530. }
  1531. // Modulus
  1532. pbModulus = pbMessage;
  1533. pbMessage += cbModulus;
  1534. // Exponent length
  1535. cbExponent = MAKEWORD(pbMessage[1], pbMessage[0]);
  1536. if(cbExponent < 1 || cbExponent > 4)
  1537. {
  1538. return SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  1539. }
  1540. pbMessage += 2;
  1541. // Exponent
  1542. pbExponent = pbMessage;
  1543. pbMessage += cbExponent;
  1544. // form a (little endian) DWORD from exponent data
  1545. dwExponent = 0;
  1546. for(i = 0; i < cbExponent; i++)
  1547. {
  1548. dwExponent <<= 8;
  1549. dwExponent |= pbExponent[i];
  1550. }
  1551. // Compute length of ServerRSAParams structure.
  1552. cbServerParams = (DWORD)(pbMessage - pbServerParams);
  1553. //
  1554. // digitally-signed struct {
  1555. // select(SignatureAlgorithm) {
  1556. // case anonymous: struct { };
  1557. // case rsa:
  1558. // opaque md5_hash[16];
  1559. // opaque sha_hash[20];
  1560. // case dsa:
  1561. // opaque sha_hash[20];
  1562. // };
  1563. // } Signature;
  1564. //
  1565. {
  1566. BYTE rgbHashValue[CB_MD5_DIGEST_LEN + CB_SHA_DIGEST_LEN];
  1567. PBYTE pbSignature;
  1568. DWORD cbSignature;
  1569. HCRYPTHASH hHash;
  1570. PBYTE pbLocalBuffer;
  1571. DWORD cbLocalBuffer;
  1572. // Signature block length
  1573. cbSignature = ((INT)pbMessage[0] << 8) + pbMessage[1];
  1574. pbMessage += 2;
  1575. pbSignature = pbMessage;
  1576. // Allocate buffer for RSA operation.
  1577. cbLocalBuffer = cbSignature;
  1578. pbLocalBuffer = SPExternalAlloc(cbLocalBuffer);
  1579. if(pbLocalBuffer == NULL)
  1580. {
  1581. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1582. }
  1583. // Reverse the signature.
  1584. ReverseMemCopy(pbLocalBuffer, pbSignature, cbSignature);
  1585. // Compute MD5 and SHA hash values.
  1586. ComputeServerExchangeHashes(pContext,
  1587. pbServerParams,
  1588. cbServerParams,
  1589. rgbHashValue,
  1590. rgbHashValue + CB_MD5_DIGEST_LEN);
  1591. if(!SchCryptCreateHash(pContext->RipeZombie->hMasterProv,
  1592. CALG_SSL3_SHAMD5,
  1593. 0,
  1594. 0,
  1595. &hHash,
  1596. pContext->RipeZombie->dwCapiFlags))
  1597. {
  1598. SP_LOG_RESULT(GetLastError());
  1599. SPExternalFree(pbLocalBuffer);
  1600. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1601. }
  1602. // set hash value
  1603. if(!SchCryptSetHashParam(hHash,
  1604. HP_HASHVAL,
  1605. rgbHashValue,
  1606. 0,
  1607. pContext->RipeZombie->dwCapiFlags))
  1608. {
  1609. SP_LOG_RESULT(GetLastError());
  1610. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  1611. SPExternalFree(pbLocalBuffer);
  1612. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1613. }
  1614. DebugLog((DEB_TRACE, "Verify server_key_exchange message signature.\n"));
  1615. if(!SchCryptVerifySignature(hHash,
  1616. pbLocalBuffer,
  1617. cbSignature,
  1618. hServerPublic,
  1619. NULL,
  1620. 0,
  1621. pContext->RipeZombie->dwCapiFlags))
  1622. {
  1623. DebugLog((DEB_WARN, "Signature Verify Failed: %x\n", GetLastError()));
  1624. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  1625. SPExternalFree(pbLocalBuffer);
  1626. return SP_LOG_RESULT(PCT_ERR_INTEGRITY_CHECK_FAILED);
  1627. }
  1628. DebugLog((DEB_TRACE, "Server_key_exchange message signature verified okay.\n"));
  1629. SchCryptDestroyHash(hHash, pContext->RipeZombie->dwCapiFlags);
  1630. SPExternalFree(pbLocalBuffer);
  1631. }
  1632. //
  1633. // Import ephemeral public key into CSP.
  1634. //
  1635. {
  1636. BLOBHEADER *pBlobHeader;
  1637. RSAPUBKEY *pRsaPubKey;
  1638. PBYTE pbBlob;
  1639. DWORD cbBlob;
  1640. // Allocate memory for PUBLICKEYBLOB.
  1641. cbBlob = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + cbModulus;
  1642. pbBlob = SPExternalAlloc(cbBlob);
  1643. if(pbBlob == NULL)
  1644. {
  1645. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1646. }
  1647. // Build PUBLICKEYBLOB from modulus and exponent.
  1648. pBlobHeader = (BLOBHEADER *)pbBlob;
  1649. pRsaPubKey = (RSAPUBKEY *)(pBlobHeader + 1);
  1650. pBlobHeader->bType = PUBLICKEYBLOB;
  1651. pBlobHeader->bVersion = CUR_BLOB_VERSION;
  1652. pBlobHeader->reserved = 0;
  1653. pBlobHeader->aiKeyAlg = CALG_RSA_KEYX;
  1654. pRsaPubKey->magic = 0x31415352; // RSA1
  1655. pRsaPubKey->bitlen = cbModulus * 8;
  1656. pRsaPubKey->pubexp = dwExponent;
  1657. ReverseMemCopy((PBYTE)(pRsaPubKey + 1), pbModulus, cbModulus);
  1658. if(!SchCryptImportKey(pContext->RipeZombie->hMasterProv,
  1659. pbBlob,
  1660. cbBlob,
  1661. 0,
  1662. 0,
  1663. phNewServerPublic,
  1664. pContext->RipeZombie->dwCapiFlags))
  1665. {
  1666. SP_LOG_RESULT(GetLastError());
  1667. SPExternalFree(pbBlob);
  1668. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1669. }
  1670. SPExternalFree(pbBlob);
  1671. }
  1672. return PCT_ERR_OK;
  1673. }