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.

819 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: serial.c
  7. //
  8. // Contents: Schannel context serialization routines.
  9. //
  10. // Functions: SPContextSerialize
  11. // SPContextDeserialize
  12. //
  13. // History: 02-15-00 jbanes Created.
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <spbase.h>
  17. #include <certmap.h>
  18. #include <mapper.h>
  19. #include <align.h>
  20. typedef enum _SERIALIZED_ITEM_TYPE
  21. {
  22. SslEndOfBuffer = 0,
  23. SslContext,
  24. SslReadKey,
  25. SslReadMac,
  26. SslWriteKey,
  27. SslWriteMac,
  28. SslMapper,
  29. SslRemoteCertificate
  30. } SERIALIZED_ITEM_TYPE;
  31. typedef struct _SERIALIZED_ITEM_TAG
  32. {
  33. DWORD Type;
  34. DWORD Length;
  35. DWORD DataLength;
  36. DWORD reserved;
  37. } SERIALIZED_ITEM_TAG;
  38. #define TAG_LENGTH sizeof(SERIALIZED_ITEM_TAG)
  39. DWORD
  40. GetSerializedKeyLength(
  41. HCRYPTKEY hKey)
  42. {
  43. DWORD cbKey;
  44. if(!CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, NULL, &cbKey))
  45. {
  46. SP_LOG_RESULT(GetLastError());
  47. return 0;
  48. }
  49. return ROUND_UP_COUNT(TAG_LENGTH + cbKey, ALIGN_LPVOID);
  50. }
  51. SP_STATUS
  52. SerializeKey(
  53. HCRYPTKEY hKey,
  54. SERIALIZED_ITEM_TYPE Type,
  55. PBYTE pbBuffer,
  56. PDWORD pcbBuffer)
  57. {
  58. SERIALIZED_ITEM_TAG *pTag;
  59. PBYTE pbKey;
  60. DWORD cbKey;
  61. if(*pcbBuffer <= TAG_LENGTH)
  62. {
  63. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  64. }
  65. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  66. pbKey = pbBuffer + TAG_LENGTH;
  67. cbKey = *pcbBuffer - TAG_LENGTH;
  68. if(!CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, pbKey, &cbKey))
  69. {
  70. SP_LOG_RESULT(GetLastError());
  71. return PCT_INT_INTERNAL_ERROR;
  72. }
  73. pTag->Type = Type;
  74. pTag->Length = ROUND_UP_COUNT(cbKey, ALIGN_LPVOID);
  75. pTag->DataLength = cbKey;
  76. if(*pcbBuffer <= TAG_LENGTH + pTag->Length)
  77. {
  78. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  79. }
  80. *pcbBuffer = TAG_LENGTH + pTag->Length;
  81. return PCT_ERR_OK;
  82. }
  83. SP_STATUS
  84. SerializeContext(
  85. PSPContext pContext,
  86. SERIALIZE_LOCATOR_FN LocatorMove,
  87. PBYTE pbBuffer,
  88. PDWORD pcbBuffer,
  89. BOOL fDestroyKeys)
  90. {
  91. DWORD cbData;
  92. DWORD cbBuffer;
  93. DWORD cbBytesNeeded;
  94. SERIALIZED_ITEM_TAG *pTag;
  95. PSessCacheItem pZombie;
  96. SP_STATUS pctRet;
  97. //
  98. // Initialize buffer pointers.
  99. //
  100. if(pbBuffer == NULL)
  101. {
  102. cbBuffer = 0;
  103. }
  104. else
  105. {
  106. cbBuffer = *pcbBuffer;
  107. }
  108. pZombie = pContext->RipeZombie;
  109. //
  110. // Context structure.
  111. //
  112. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + sizeof(SPPackedContext),
  113. ALIGN_LPVOID);
  114. if(pbBuffer == NULL)
  115. {
  116. cbBuffer += cbBytesNeeded;
  117. }
  118. else
  119. {
  120. PSPPackedContext pSerialContext;
  121. HLOCATOR hLocator;
  122. if(cbBuffer < cbBytesNeeded)
  123. {
  124. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  125. }
  126. pContext->Flags |= CONTEXT_FLAG_SERIALIZED;
  127. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  128. pSerialContext = (PSPPackedContext)(pbBuffer + TAG_LENGTH);
  129. pTag->Type = SslContext;
  130. pTag->Length = cbBytesNeeded - TAG_LENGTH;
  131. pSerialContext->Magic = pContext->Magic;
  132. pSerialContext->State = pContext->State;
  133. pSerialContext->Flags = pContext->Flags;
  134. pSerialContext->dwProtocol = pContext->dwProtocol;
  135. pSerialContext->ContextThumbprint = pContext->ContextThumbprint;
  136. pSerialContext->dwCipherInfo = (DWORD)(pContext->pCipherInfo - g_AvailableCiphers);
  137. pSerialContext->dwHashInfo = (DWORD)(pContext->pHashInfo - g_AvailableHashes);
  138. pSerialContext->dwKeyExchInfo = (DWORD)(pContext->pKeyExchInfo - g_AvailableExch);
  139. pSerialContext->dwExchStrength = pContext->RipeZombie->dwExchStrength;
  140. pSerialContext->ReadCounter = pContext->ReadCounter;
  141. pSerialContext->WriteCounter = pContext->WriteCounter;
  142. if(pZombie->fProtocol & SP_PROT_SERVERS)
  143. {
  144. if(pZombie->pActiveServerCred)
  145. {
  146. #ifdef _WIN64
  147. pSerialContext->hMasterProv.QuadPart = (ULONGLONG)pZombie->pActiveServerCred->hRemoteProv;
  148. #else
  149. pSerialContext->hMasterProv.LowPart = (DWORD)pZombie->pActiveServerCred->hRemoteProv;
  150. #endif
  151. }
  152. // Copy the locator.
  153. if(pZombie->phMapper && pZombie->hLocator && LocatorMove)
  154. {
  155. LocatorMove(pZombie->hLocator, &hLocator);
  156. #ifdef _WIN64
  157. pSerialContext->hLocator.QuadPart = (ULONGLONG)hLocator;
  158. #else
  159. pSerialContext->hLocator.LowPart = (DWORD)hLocator;
  160. #endif
  161. }
  162. pSerialContext->LocatorStatus = pZombie->LocatorStatus;
  163. }
  164. pSerialContext->cbSessionID = pZombie->cbSessionID;
  165. memcpy(pSerialContext->SessionID, pZombie->SessionID, pZombie->cbSessionID);
  166. pbBuffer += cbBytesNeeded;
  167. cbBuffer -= cbBytesNeeded;
  168. }
  169. //
  170. // Certificate mapper structure.
  171. //
  172. if(pContext->RipeZombie->phMapper)
  173. {
  174. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + sizeof(PVOID),
  175. ALIGN_LPVOID);
  176. if(pbBuffer == NULL)
  177. {
  178. cbBuffer += cbBytesNeeded;
  179. }
  180. else
  181. {
  182. if(cbBuffer < cbBytesNeeded)
  183. {
  184. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  185. }
  186. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  187. pTag->Type = SslMapper;
  188. pTag->Length = cbBytesNeeded - TAG_LENGTH;
  189. CopyMemory(pbBuffer + TAG_LENGTH,
  190. &pZombie->phMapper->m_Reserved1,
  191. sizeof(PVOID));
  192. pbBuffer += cbBytesNeeded;
  193. cbBuffer -= cbBytesNeeded;
  194. }
  195. }
  196. //
  197. // Data encryption and MAC keys.
  198. //
  199. if(pContext->pCipherInfo->aiCipher != CALG_NULLCIPHER)
  200. {
  201. // Read key.
  202. if(pbBuffer == NULL)
  203. {
  204. cbBuffer += GetSerializedKeyLength(pContext->hReadKey);
  205. }
  206. else
  207. {
  208. cbData = cbBuffer;
  209. pctRet = SerializeKey(pContext->hReadKey,
  210. SslReadKey,
  211. pbBuffer,
  212. &cbData);
  213. if(pctRet != PCT_ERR_OK)
  214. {
  215. return pctRet;
  216. }
  217. if(fDestroyKeys)
  218. {
  219. if(!CryptDestroyKey(pContext->hReadKey))
  220. {
  221. SP_LOG_RESULT(GetLastError());
  222. }
  223. pContext->hReadKey = 0;
  224. }
  225. pbBuffer += cbData;
  226. cbBuffer -= cbData;
  227. }
  228. // Write key.
  229. if(pbBuffer == NULL)
  230. {
  231. cbBuffer += GetSerializedKeyLength(pContext->hWriteKey);
  232. }
  233. else
  234. {
  235. cbData = cbBuffer;
  236. pctRet = SerializeKey(pContext->hWriteKey,
  237. SslWriteKey,
  238. pbBuffer,
  239. &cbData);
  240. if(pctRet != PCT_ERR_OK)
  241. {
  242. return pctRet;
  243. }
  244. if(fDestroyKeys)
  245. {
  246. if(!CryptDestroyKey(pContext->hWriteKey))
  247. {
  248. SP_LOG_RESULT(GetLastError());
  249. }
  250. pContext->hWriteKey = 0;
  251. }
  252. pbBuffer += cbData;
  253. cbBuffer -= cbData;
  254. }
  255. }
  256. // Read MAC.
  257. if(pContext->hReadMAC)
  258. {
  259. if(pbBuffer == NULL)
  260. {
  261. cbBuffer += GetSerializedKeyLength(pContext->hReadMAC);
  262. }
  263. else
  264. {
  265. cbData = cbBuffer;
  266. pctRet = SerializeKey(pContext->hReadMAC,
  267. SslReadMac,
  268. pbBuffer,
  269. &cbData);
  270. if(pctRet != PCT_ERR_OK)
  271. {
  272. return pctRet;
  273. }
  274. pbBuffer += cbData;
  275. cbBuffer -= cbData;
  276. }
  277. }
  278. // Write MAC.
  279. if(pContext->hWriteMAC)
  280. {
  281. if(pbBuffer == NULL)
  282. {
  283. cbBuffer += GetSerializedKeyLength(pContext->hWriteMAC);
  284. }
  285. else
  286. {
  287. cbData = cbBuffer;
  288. pctRet = SerializeKey(pContext->hWriteMAC,
  289. SslWriteMac,
  290. pbBuffer,
  291. &cbData);
  292. if(pctRet != PCT_ERR_OK)
  293. {
  294. return pctRet;
  295. }
  296. pbBuffer += cbData;
  297. cbBuffer -= cbData;
  298. }
  299. }
  300. //
  301. // Remote certificate.
  302. //
  303. if(pContext->RipeZombie->pRemoteCert)
  304. {
  305. if(pbBuffer == NULL)
  306. {
  307. pctRet = SerializeCertContext(pContext->RipeZombie->pRemoteCert,
  308. NULL,
  309. &cbData);
  310. if(pctRet != PCT_ERR_OK)
  311. {
  312. return SP_LOG_RESULT(pctRet);
  313. }
  314. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + cbData, ALIGN_LPVOID);
  315. cbBuffer += cbBytesNeeded;
  316. }
  317. else
  318. {
  319. if(cbBuffer < TAG_LENGTH)
  320. {
  321. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  322. }
  323. cbData = cbBuffer - TAG_LENGTH;
  324. pctRet = SerializeCertContext(pContext->RipeZombie->pRemoteCert,
  325. pbBuffer + TAG_LENGTH,
  326. &cbData);
  327. if(pctRet != PCT_ERR_OK)
  328. {
  329. return SP_LOG_RESULT(pctRet);
  330. }
  331. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + cbData, ALIGN_LPVOID);
  332. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  333. pTag->Type = SslRemoteCertificate;
  334. pTag->Length = cbBytesNeeded - TAG_LENGTH;
  335. pbBuffer += cbBytesNeeded;
  336. cbBuffer -= cbBytesNeeded;
  337. }
  338. }
  339. //
  340. // End of buffer marker.
  341. //
  342. if(pbBuffer == NULL)
  343. {
  344. cbBuffer += TAG_LENGTH;
  345. }
  346. else
  347. {
  348. if(cbBuffer < TAG_LENGTH)
  349. {
  350. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  351. }
  352. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  353. pTag->Type = SslEndOfBuffer;
  354. pTag->Length = 0;
  355. pbBuffer += TAG_LENGTH;
  356. cbBuffer -= TAG_LENGTH;
  357. }
  358. if(pbBuffer == NULL)
  359. {
  360. *pcbBuffer = cbBuffer;
  361. }
  362. else
  363. {
  364. #if DBG
  365. if(cbBuffer)
  366. {
  367. DebugLog((DEB_WARN, "%d bytes left over when serializing context.\n", cbBuffer));
  368. }
  369. #endif
  370. }
  371. return PCT_ERR_OK;
  372. }
  373. //+---------------------------------------------------------------------------
  374. //
  375. // Function: SPContextSerialize
  376. //
  377. // Synopsis: Extract out everything necessary for bulk data encryption
  378. // from an Schannel context, and place it in a linear buffer.
  379. //
  380. // Arguments: [pCred] -- Context to be serialized.
  381. // [ppBuffer] -- Destination buffer.
  382. // [pcbBuffer] -- Destination buffer length.
  383. //
  384. // History: 09-25-96 jbanes Hacked for LSA integration.
  385. //
  386. // Notes: This routine is called by the LSA process when transitioning
  387. // from the handshaking phase to the bulk encryption phase.
  388. //
  389. // This function is also called by the application process as
  390. // part of ExportSecurityContext.
  391. //
  392. //----------------------------------------------------------------------------
  393. SP_STATUS
  394. SPContextSerialize(
  395. PSPContext pContext,
  396. SERIALIZE_LOCATOR_FN LocatorMove,
  397. PBYTE * ppBuffer,
  398. PDWORD pcbBuffer,
  399. BOOL fDestroyKeys)
  400. {
  401. PBYTE pbBuffer;
  402. DWORD cbBuffer;
  403. SP_STATUS pctRet;
  404. // Determine size of serialized buffer.
  405. pctRet = SerializeContext(pContext, LocatorMove, NULL, &cbBuffer, fDestroyKeys);
  406. if(pctRet != PCT_ERR_OK)
  407. {
  408. return SP_LOG_RESULT(pctRet);
  409. }
  410. // Allocate memory for serialized buffer.
  411. pbBuffer = SPExternalAlloc(cbBuffer);
  412. if(pbBuffer == NULL)
  413. {
  414. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  415. }
  416. // Generate serialized context.
  417. pctRet = SerializeContext(pContext, LocatorMove, pbBuffer, &cbBuffer, fDestroyKeys);
  418. if(pctRet != PCT_ERR_OK)
  419. {
  420. SPExternalFree(pbBuffer);
  421. return SP_LOG_RESULT(pctRet);
  422. }
  423. // Set outputs
  424. *ppBuffer = pbBuffer;
  425. *pcbBuffer = cbBuffer;
  426. return PCT_ERR_OK;
  427. }
  428. //+---------------------------------------------------------------------------
  429. //
  430. // Function: SPContextDeserialize
  431. //
  432. // Synopsis: Build an Schannel context structure from a linear buffer,
  433. // which was created via SPContextSerialize by the other
  434. // process.
  435. //
  436. // Arguments: [pBuffer] -- Buffer containing serialized context.
  437. // The new context structure is built over
  438. // the top of this buffer.
  439. //
  440. // History: 09-25-96 jbanes Hacked for LSA integration.
  441. //
  442. // Notes: This routine is called by the application process when
  443. // transitioning from the handshaking phase to the bulk
  444. // encryption phase.
  445. //
  446. //----------------------------------------------------------------------------
  447. SP_STATUS
  448. SPContextDeserialize(
  449. PBYTE pbBuffer,
  450. PSPContext *ppContext)
  451. {
  452. PSPContext pContext = NULL;
  453. DWORD Status = PCT_INT_INTERNAL_ERROR;
  454. BOOL fDone;
  455. PSPPackedContext pSerialContext;
  456. PSessCacheItem pZombie;
  457. SERIALIZED_ITEM_TAG *pTag;
  458. DWORD cbContext;
  459. DebugLog((DEB_TRACE, "Deserialize context\n"));
  460. //
  461. // Extract serialized context.
  462. //
  463. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  464. if(pTag->Type != SslContext)
  465. {
  466. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  467. }
  468. if(pTag->Length < sizeof(PSPPackedContext))
  469. {
  470. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  471. }
  472. pSerialContext = (PSPPackedContext)(pbBuffer + TAG_LENGTH);
  473. cbContext = ROUND_UP_COUNT(sizeof(SPContext), ALIGN_LPVOID);
  474. pContext = SPExternalAlloc(cbContext + sizeof(SessCacheItem));
  475. if(pContext == NULL)
  476. {
  477. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  478. }
  479. pContext->RipeZombie = (PSessCacheItem)((PBYTE)pContext + cbContext);
  480. pZombie = pContext->RipeZombie;
  481. pContext->Magic = pSerialContext->Magic;
  482. pContext->State = pSerialContext->State;
  483. pContext->Flags = pSerialContext->Flags;
  484. pContext->dwProtocol = pSerialContext->dwProtocol;
  485. pContext->ContextThumbprint = pSerialContext->ContextThumbprint;
  486. pContext->pCipherInfo = g_AvailableCiphers + pSerialContext->dwCipherInfo;
  487. pContext->pHashInfo = g_AvailableHashes + pSerialContext->dwHashInfo;
  488. pContext->pKeyExchInfo = g_AvailableExch + pSerialContext->dwKeyExchInfo;
  489. pContext->pReadCipherInfo = pContext->pCipherInfo;
  490. pContext->pWriteCipherInfo = pContext->pCipherInfo;
  491. pContext->pReadHashInfo = pContext->pHashInfo;
  492. pContext->pWriteHashInfo = pContext->pHashInfo;
  493. pContext->ReadCounter = pSerialContext->ReadCounter;
  494. pContext->WriteCounter = pSerialContext->WriteCounter;
  495. pContext->InitiateHello = GenerateHello;
  496. switch(pContext->dwProtocol)
  497. {
  498. case SP_PROT_PCT1_CLIENT:
  499. pContext->Decrypt = Pct1DecryptMessage;
  500. pContext->Encrypt = Pct1EncryptMessage;
  501. pContext->ProtocolHandler = Pct1ClientProtocolHandler;
  502. pContext->DecryptHandler = Pct1DecryptHandler;
  503. pContext->GetHeaderSize = Pct1GetHeaderSize;
  504. break;
  505. case SP_PROT_PCT1_SERVER:
  506. pContext->Decrypt = Pct1DecryptMessage;
  507. pContext->Encrypt = Pct1EncryptMessage;
  508. pContext->ProtocolHandler = Pct1ServerProtocolHandler;
  509. pContext->DecryptHandler = Pct1DecryptHandler;
  510. pContext->GetHeaderSize = Pct1GetHeaderSize;
  511. break;
  512. case SP_PROT_SSL2_CLIENT:
  513. pContext->Decrypt = Ssl2DecryptMessage;
  514. pContext->Encrypt = Ssl2EncryptMessage;
  515. pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
  516. pContext->DecryptHandler = Ssl2DecryptHandler;
  517. pContext->GetHeaderSize = Ssl2GetHeaderSize;
  518. break;
  519. case SP_PROT_SSL2_SERVER:
  520. pContext->Decrypt = Ssl2DecryptMessage;
  521. pContext->Encrypt = Ssl2EncryptMessage;
  522. pContext->ProtocolHandler = Ssl2ServerProtocolHandler;
  523. pContext->DecryptHandler = Ssl2DecryptHandler;
  524. pContext->GetHeaderSize = Ssl2GetHeaderSize;
  525. break;
  526. case SP_PROT_SSL3_CLIENT:
  527. case SP_PROT_SSL3_SERVER:
  528. case SP_PROT_TLS1_CLIENT:
  529. case SP_PROT_TLS1_SERVER:
  530. pContext->Decrypt = Ssl3DecryptMessage;
  531. pContext->Encrypt = Ssl3EncryptMessage;
  532. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  533. pContext->DecryptHandler = Ssl3DecryptHandler;
  534. pContext->GetHeaderSize = Ssl3GetHeaderSize;
  535. break;
  536. default:
  537. pContext->Decrypt = NULL;
  538. pContext->Encrypt = NULL;
  539. pContext->ProtocolHandler = NULL;
  540. pContext->DecryptHandler = NULL;
  541. pContext->GetHeaderSize = NULL;
  542. }
  543. //
  544. // Extract serialized cache entry.
  545. //
  546. pZombie->fProtocol = pSerialContext->dwProtocol;
  547. pZombie->dwExchStrength = pSerialContext->dwExchStrength;
  548. #ifdef _WIN64
  549. pZombie->hLocator = (HLOCATOR)pSerialContext->hLocator.QuadPart;
  550. pZombie->hMasterProv = (HCRYPTPROV)pSerialContext->hMasterProv.QuadPart;
  551. #else
  552. pZombie->hLocator = (HLOCATOR)pSerialContext->hLocator.LowPart;
  553. pZombie->hMasterProv = (HCRYPTPROV)pSerialContext->hMasterProv.LowPart;
  554. #endif
  555. pZombie->LocatorStatus = pSerialContext->LocatorStatus;
  556. pZombie->cbSessionID = pSerialContext->cbSessionID;
  557. memcpy(pZombie->SessionID, pSerialContext->SessionID, pSerialContext->cbSessionID);
  558. switch(pContext->pKeyExchInfo->Spec)
  559. {
  560. case SP_EXCH_RSA_PKCS1:
  561. if((pZombie->fProtocol & SP_PROT_CLIENTS) || !pZombie->hMasterProv)
  562. {
  563. pZombie->hMasterProv = g_hRsaSchannel;
  564. }
  565. break;
  566. case SP_EXCH_DH_PKCS3:
  567. if((pZombie->fProtocol & SP_PROT_CLIENTS) || !pZombie->hMasterProv)
  568. {
  569. pZombie->hMasterProv = g_hDhSchannelProv;
  570. }
  571. break;
  572. default:
  573. Status = SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  574. goto cleanup;
  575. }
  576. pContext->hReadProv = pZombie->hMasterProv;
  577. pContext->hWriteProv = pZombie->hMasterProv;
  578. pbBuffer += TAG_LENGTH + pTag->Length;
  579. //
  580. // Extract optional serialized data.
  581. //
  582. fDone = FALSE;
  583. while(!fDone)
  584. {
  585. DWORD Type = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->Type;
  586. DWORD Length = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->Length;
  587. DWORD DataLength = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->DataLength;
  588. pbBuffer += TAG_LENGTH;
  589. switch(Type)
  590. {
  591. case SslEndOfBuffer:
  592. DebugLog((DEB_TRACE, "SslEndOfBuffer\n"));
  593. fDone = TRUE;
  594. break;
  595. case SslReadKey:
  596. DebugLog((DEB_TRACE, "SslReadKey\n"));
  597. if(!CryptImportKey(pZombie->hMasterProv,
  598. pbBuffer,
  599. DataLength,
  600. 0, 0,
  601. &pContext->hReadKey))
  602. {
  603. SP_LOG_RESULT(GetLastError());
  604. Status = PCT_INT_INTERNAL_ERROR;
  605. goto cleanup;
  606. }
  607. DebugLog((DEB_TRACE, "Key:0x%p\n", pContext->hReadKey));
  608. break;
  609. case SslReadMac:
  610. DebugLog((DEB_TRACE, "SslReadMac\n"));
  611. if(!CryptImportKey(pZombie->hMasterProv,
  612. pbBuffer,
  613. DataLength,
  614. 0, 0,
  615. &pContext->hReadMAC))
  616. {
  617. SP_LOG_RESULT(GetLastError());
  618. Status = PCT_INT_INTERNAL_ERROR;
  619. goto cleanup;
  620. }
  621. break;
  622. case SslWriteKey:
  623. DebugLog((DEB_TRACE, "SslWriteKey\n"));
  624. if(!CryptImportKey(pZombie->hMasterProv,
  625. pbBuffer,
  626. DataLength,
  627. 0, 0,
  628. &pContext->hWriteKey))
  629. {
  630. SP_LOG_RESULT(GetLastError());
  631. Status = PCT_INT_INTERNAL_ERROR;
  632. goto cleanup;
  633. }
  634. DebugLog((DEB_TRACE, "Key:0x%p\n", pContext->hWriteKey));
  635. break;
  636. case SslWriteMac:
  637. DebugLog((DEB_TRACE, "SslWriteMac\n"));
  638. if(!CryptImportKey(pZombie->hMasterProv,
  639. pbBuffer,
  640. DataLength,
  641. 0, 0,
  642. &pContext->hWriteMAC))
  643. {
  644. SP_LOG_RESULT(GetLastError());
  645. Status = PCT_INT_INTERNAL_ERROR;
  646. goto cleanup;
  647. }
  648. break;
  649. case SslMapper:
  650. DebugLog((DEB_TRACE, "SslMapper\n"));
  651. pZombie->phMapper = *(HMAPPER **)pbBuffer;
  652. break;
  653. case SslRemoteCertificate:
  654. DebugLog((DEB_TRACE, "SslRemoteCertificate\n"));
  655. // Save a pointer to the serialized certificate context
  656. // of the remote certificate. This will be deserialized
  657. // by the QueryContextAttribute function when the
  658. // application asks for it.
  659. pZombie->pbServerCertificate = SPExternalAlloc(Length);
  660. if(pZombie->pbServerCertificate)
  661. {
  662. memcpy(pZombie->pbServerCertificate, pbBuffer, Length);
  663. pZombie->cbServerCertificate = Length;
  664. }
  665. break;
  666. default:
  667. DebugLog((DEB_WARN, "Invalid tag %d found when deserializing context buffer\n"));
  668. Status = PCT_INT_INTERNAL_ERROR;
  669. goto cleanup;
  670. }
  671. pbBuffer += Length;
  672. }
  673. *ppContext = pContext;
  674. pContext = NULL;
  675. Status = PCT_ERR_OK;
  676. cleanup:
  677. if(pContext != NULL)
  678. {
  679. LsaContextDelete(pContext);
  680. SPExternalFree(pContext);
  681. }
  682. return Status;
  683. }