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.

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