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.

836 lines
23 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. if(pZombie->phMapper->m_dwFlags & SCH_FLAG_SYSTEM_MAPPER)
  156. {
  157. // The locator belongs to the system mapper and consists
  158. // of a user token, so use the DuplicateHandle function
  159. // to make a copy.
  160. LocatorMove(pZombie->hLocator, &hLocator);
  161. }
  162. else
  163. {
  164. hLocator = pZombie->hLocator;
  165. }
  166. #ifdef _WIN64
  167. pSerialContext->hLocator.QuadPart = (ULONGLONG)hLocator;
  168. #else
  169. pSerialContext->hLocator.LowPart = (DWORD)hLocator;
  170. #endif
  171. }
  172. pSerialContext->LocatorStatus = pZombie->LocatorStatus;
  173. }
  174. pSerialContext->cbSessionID = pZombie->cbSessionID;
  175. memcpy(pSerialContext->SessionID, pZombie->SessionID, pZombie->cbSessionID);
  176. pbBuffer += cbBytesNeeded;
  177. cbBuffer -= cbBytesNeeded;
  178. }
  179. //
  180. // Certificate mapper structure.
  181. //
  182. if(pContext->RipeZombie->phMapper)
  183. {
  184. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + sizeof(PVOID),
  185. ALIGN_LPVOID);
  186. if(pbBuffer == NULL)
  187. {
  188. cbBuffer += cbBytesNeeded;
  189. }
  190. else
  191. {
  192. if(cbBuffer < cbBytesNeeded)
  193. {
  194. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  195. }
  196. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  197. pTag->Type = SslMapper;
  198. pTag->Length = cbBytesNeeded - TAG_LENGTH;
  199. CopyMemory(pbBuffer + TAG_LENGTH,
  200. &pZombie->phMapper->m_Reserved1,
  201. sizeof(PVOID));
  202. pbBuffer += cbBytesNeeded;
  203. cbBuffer -= cbBytesNeeded;
  204. }
  205. }
  206. //
  207. // Data encryption and MAC keys.
  208. //
  209. if(pContext->pCipherInfo->aiCipher != CALG_NULLCIPHER)
  210. {
  211. // Read key.
  212. if(pbBuffer == NULL)
  213. {
  214. cbBuffer += GetSerializedKeyLength(pContext->hReadKey);
  215. }
  216. else
  217. {
  218. cbData = cbBuffer;
  219. pctRet = SerializeKey(pContext->hReadKey,
  220. SslReadKey,
  221. pbBuffer,
  222. &cbData);
  223. if(pctRet != PCT_ERR_OK)
  224. {
  225. return pctRet;
  226. }
  227. if(fDestroyKeys)
  228. {
  229. if(!CryptDestroyKey(pContext->hReadKey))
  230. {
  231. SP_LOG_RESULT(GetLastError());
  232. }
  233. pContext->hReadKey = 0;
  234. }
  235. pbBuffer += cbData;
  236. cbBuffer -= cbData;
  237. }
  238. // Write key.
  239. if(pbBuffer == NULL)
  240. {
  241. cbBuffer += GetSerializedKeyLength(pContext->hWriteKey);
  242. }
  243. else
  244. {
  245. cbData = cbBuffer;
  246. pctRet = SerializeKey(pContext->hWriteKey,
  247. SslWriteKey,
  248. pbBuffer,
  249. &cbData);
  250. if(pctRet != PCT_ERR_OK)
  251. {
  252. return pctRet;
  253. }
  254. if(fDestroyKeys)
  255. {
  256. if(!CryptDestroyKey(pContext->hWriteKey))
  257. {
  258. SP_LOG_RESULT(GetLastError());
  259. }
  260. pContext->hWriteKey = 0;
  261. }
  262. pbBuffer += cbData;
  263. cbBuffer -= cbData;
  264. }
  265. }
  266. // Read MAC.
  267. if(pContext->hReadMAC)
  268. {
  269. if(pbBuffer == NULL)
  270. {
  271. cbBuffer += GetSerializedKeyLength(pContext->hReadMAC);
  272. }
  273. else
  274. {
  275. cbData = cbBuffer;
  276. pctRet = SerializeKey(pContext->hReadMAC,
  277. SslReadMac,
  278. pbBuffer,
  279. &cbData);
  280. if(pctRet != PCT_ERR_OK)
  281. {
  282. return pctRet;
  283. }
  284. pbBuffer += cbData;
  285. cbBuffer -= cbData;
  286. }
  287. }
  288. // Write MAC.
  289. if(pContext->hWriteMAC)
  290. {
  291. if(pbBuffer == NULL)
  292. {
  293. cbBuffer += GetSerializedKeyLength(pContext->hWriteMAC);
  294. }
  295. else
  296. {
  297. cbData = cbBuffer;
  298. pctRet = SerializeKey(pContext->hWriteMAC,
  299. SslWriteMac,
  300. pbBuffer,
  301. &cbData);
  302. if(pctRet != PCT_ERR_OK)
  303. {
  304. return pctRet;
  305. }
  306. pbBuffer += cbData;
  307. cbBuffer -= cbData;
  308. }
  309. }
  310. //
  311. // Remote certificate.
  312. //
  313. if(pContext->RipeZombie->pRemoteCert)
  314. {
  315. if(pbBuffer == NULL)
  316. {
  317. pctRet = SerializeCertContext(pContext->RipeZombie->pRemoteCert,
  318. NULL,
  319. &cbData);
  320. if(pctRet != PCT_ERR_OK)
  321. {
  322. return SP_LOG_RESULT(pctRet);
  323. }
  324. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + cbData, ALIGN_LPVOID);
  325. cbBuffer += cbBytesNeeded;
  326. }
  327. else
  328. {
  329. if(cbBuffer < TAG_LENGTH)
  330. {
  331. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  332. }
  333. cbData = cbBuffer - TAG_LENGTH;
  334. pctRet = SerializeCertContext(pContext->RipeZombie->pRemoteCert,
  335. pbBuffer + TAG_LENGTH,
  336. &cbData);
  337. if(pctRet != PCT_ERR_OK)
  338. {
  339. return SP_LOG_RESULT(pctRet);
  340. }
  341. cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + cbData, ALIGN_LPVOID);
  342. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  343. pTag->Type = SslRemoteCertificate;
  344. pTag->Length = cbBytesNeeded - TAG_LENGTH;
  345. pbBuffer += cbBytesNeeded;
  346. cbBuffer -= cbBytesNeeded;
  347. }
  348. }
  349. //
  350. // End of buffer marker.
  351. //
  352. if(pbBuffer == NULL)
  353. {
  354. cbBuffer += TAG_LENGTH;
  355. }
  356. else
  357. {
  358. if(cbBuffer < TAG_LENGTH)
  359. {
  360. return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
  361. }
  362. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  363. pTag->Type = SslEndOfBuffer;
  364. pTag->Length = 0;
  365. pbBuffer += TAG_LENGTH;
  366. cbBuffer -= TAG_LENGTH;
  367. }
  368. if(pbBuffer == NULL)
  369. {
  370. *pcbBuffer = cbBuffer;
  371. }
  372. else
  373. {
  374. #if DBG
  375. if(cbBuffer)
  376. {
  377. DebugLog((DEB_WARN, "%d bytes left over when serializing context.\n", cbBuffer));
  378. }
  379. #endif
  380. }
  381. return PCT_ERR_OK;
  382. }
  383. //+---------------------------------------------------------------------------
  384. //
  385. // Function: SPContextSerialize
  386. //
  387. // Synopsis: Extract out everything necessary for bulk data encryption
  388. // from an Schannel context, and place it in a linear buffer.
  389. //
  390. // Arguments: [pCred] -- Context to be serialized.
  391. // [ppBuffer] -- Destination buffer.
  392. // [pcbBuffer] -- Destination buffer length.
  393. //
  394. // History: 09-25-96 jbanes Hacked for LSA integration.
  395. //
  396. // Notes: This routine is called by the LSA process when transitioning
  397. // from the handshaking phase to the bulk encryption phase.
  398. //
  399. // This function is also called by the application process as
  400. // part of ExportSecurityContext.
  401. //
  402. //----------------------------------------------------------------------------
  403. SP_STATUS
  404. SPContextSerialize(
  405. PSPContext pContext,
  406. SERIALIZE_LOCATOR_FN LocatorMove,
  407. PBYTE * ppBuffer,
  408. PDWORD pcbBuffer,
  409. BOOL fDestroyKeys)
  410. {
  411. PBYTE pbBuffer;
  412. DWORD cbBuffer;
  413. SP_STATUS pctRet;
  414. // Determine size of serialized buffer.
  415. pctRet = SerializeContext(pContext, LocatorMove, NULL, &cbBuffer, fDestroyKeys);
  416. if(pctRet != PCT_ERR_OK)
  417. {
  418. return SP_LOG_RESULT(pctRet);
  419. }
  420. // Allocate memory for serialized buffer.
  421. pbBuffer = SPExternalAlloc(cbBuffer);
  422. if(pbBuffer == NULL)
  423. {
  424. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  425. }
  426. // Generate serialized context.
  427. pctRet = SerializeContext(pContext, LocatorMove, pbBuffer, &cbBuffer, fDestroyKeys);
  428. if(pctRet != PCT_ERR_OK)
  429. {
  430. SPExternalFree(pbBuffer);
  431. return SP_LOG_RESULT(pctRet);
  432. }
  433. // Set outputs
  434. *ppBuffer = pbBuffer;
  435. *pcbBuffer = cbBuffer;
  436. return PCT_ERR_OK;
  437. }
  438. //+---------------------------------------------------------------------------
  439. //
  440. // Function: SPContextDeserialize
  441. //
  442. // Synopsis: Build an Schannel context structure from a linear buffer,
  443. // which was created via SPContextSerialize by the other
  444. // process.
  445. //
  446. // Arguments: [pBuffer] -- Buffer containing serialized context.
  447. // The new context structure is built over
  448. // the top of this buffer.
  449. //
  450. // History: 09-25-96 jbanes Hacked for LSA integration.
  451. //
  452. // Notes: This routine is called by the application process when
  453. // transitioning from the handshaking phase to the bulk
  454. // encryption phase.
  455. //
  456. //----------------------------------------------------------------------------
  457. SP_STATUS
  458. SPContextDeserialize(
  459. PBYTE pbBuffer,
  460. PSPContext *ppContext)
  461. {
  462. PSPContext pContext = NULL;
  463. DWORD cbReadState;
  464. DWORD cbWriteState;
  465. HANDLE hToken;
  466. DWORD cbData;
  467. DWORD Status = PCT_INT_INTERNAL_ERROR;
  468. HMAPPER * pSerialMapper;
  469. BOOL fDone;
  470. PSPPackedContext pSerialContext;
  471. PSessCacheItem pZombie;
  472. SERIALIZED_ITEM_TAG *pTag;
  473. DWORD cbContext;
  474. DebugLog((DEB_TRACE, "Deserialize context\n"));
  475. //
  476. // Extract serialized context.
  477. //
  478. pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
  479. if(pTag->Type != SslContext)
  480. {
  481. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  482. }
  483. if(pTag->Length < sizeof(PSPPackedContext))
  484. {
  485. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  486. }
  487. pSerialContext = (PSPPackedContext)(pbBuffer + TAG_LENGTH);
  488. cbContext = ROUND_UP_COUNT(sizeof(SPContext), ALIGN_LPVOID);
  489. pContext = SPExternalAlloc(cbContext + sizeof(SessCacheItem));
  490. if(pContext == NULL)
  491. {
  492. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  493. }
  494. pContext->RipeZombie = (PSessCacheItem)((PBYTE)pContext + cbContext);
  495. pZombie = pContext->RipeZombie;
  496. pContext->Magic = pSerialContext->Magic;
  497. pContext->State = pSerialContext->State;
  498. pContext->Flags = pSerialContext->Flags;
  499. pContext->dwProtocol = pSerialContext->dwProtocol;
  500. pContext->ContextThumbprint = pSerialContext->ContextThumbprint;
  501. pContext->pCipherInfo = g_AvailableCiphers + pSerialContext->dwCipherInfo;
  502. pContext->pHashInfo = g_AvailableHashes + pSerialContext->dwHashInfo;
  503. pContext->pKeyExchInfo = g_AvailableExch + pSerialContext->dwKeyExchInfo;
  504. pContext->pReadCipherInfo = pContext->pCipherInfo;
  505. pContext->pWriteCipherInfo = pContext->pCipherInfo;
  506. pContext->pReadHashInfo = pContext->pHashInfo;
  507. pContext->pWriteHashInfo = pContext->pHashInfo;
  508. pContext->ReadCounter = pSerialContext->ReadCounter;
  509. pContext->WriteCounter = pSerialContext->WriteCounter;
  510. pContext->fAppProcess = TRUE;
  511. pContext->InitiateHello = GenerateHello;
  512. switch(pContext->dwProtocol)
  513. {
  514. case SP_PROT_PCT1_CLIENT:
  515. pContext->Decrypt = Pct1DecryptMessage;
  516. pContext->Encrypt = Pct1EncryptMessage;
  517. pContext->ProtocolHandler = Pct1ClientProtocolHandler;
  518. pContext->DecryptHandler = Pct1DecryptHandler;
  519. pContext->GetHeaderSize = Pct1GetHeaderSize;
  520. break;
  521. case SP_PROT_PCT1_SERVER:
  522. pContext->Decrypt = Pct1DecryptMessage;
  523. pContext->Encrypt = Pct1EncryptMessage;
  524. pContext->ProtocolHandler = Pct1ServerProtocolHandler;
  525. pContext->DecryptHandler = Pct1DecryptHandler;
  526. pContext->GetHeaderSize = Pct1GetHeaderSize;
  527. break;
  528. case SP_PROT_SSL2_CLIENT:
  529. pContext->Decrypt = Ssl2DecryptMessage;
  530. pContext->Encrypt = Ssl2EncryptMessage;
  531. pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
  532. pContext->DecryptHandler = Ssl2DecryptHandler;
  533. pContext->GetHeaderSize = Ssl2GetHeaderSize;
  534. break;
  535. case SP_PROT_SSL2_SERVER:
  536. pContext->Decrypt = Ssl2DecryptMessage;
  537. pContext->Encrypt = Ssl2EncryptMessage;
  538. pContext->ProtocolHandler = Ssl2ServerProtocolHandler;
  539. pContext->DecryptHandler = Ssl2DecryptHandler;
  540. pContext->GetHeaderSize = Ssl2GetHeaderSize;
  541. break;
  542. case SP_PROT_SSL3_CLIENT:
  543. case SP_PROT_SSL3_SERVER:
  544. case SP_PROT_TLS1_CLIENT:
  545. case SP_PROT_TLS1_SERVER:
  546. pContext->Decrypt = Ssl3DecryptMessage;
  547. pContext->Encrypt = Ssl3EncryptMessage;
  548. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  549. pContext->DecryptHandler = Ssl3DecryptHandler;
  550. pContext->GetHeaderSize = Ssl3GetHeaderSize;
  551. break;
  552. default:
  553. pContext->Decrypt = NULL;
  554. pContext->Encrypt = NULL;
  555. pContext->ProtocolHandler = NULL;
  556. pContext->DecryptHandler = NULL;
  557. pContext->GetHeaderSize = NULL;
  558. }
  559. //
  560. // Extract serialized cache entry.
  561. //
  562. pZombie->fProtocol = pSerialContext->dwProtocol;
  563. pZombie->dwExchStrength = pSerialContext->dwExchStrength;
  564. #ifdef _WIN64
  565. pZombie->hLocator = (HLOCATOR)pSerialContext->hLocator.QuadPart;
  566. pZombie->hMasterProv = (HCRYPTPROV)pSerialContext->hMasterProv.QuadPart;
  567. #else
  568. pZombie->hLocator = (HLOCATOR)pSerialContext->hLocator.LowPart;
  569. pZombie->hMasterProv = (HCRYPTPROV)pSerialContext->hMasterProv.LowPart;
  570. #endif
  571. pZombie->LocatorStatus = pSerialContext->LocatorStatus;
  572. pZombie->cbSessionID = pSerialContext->cbSessionID;
  573. memcpy(pZombie->SessionID, pSerialContext->SessionID, pSerialContext->cbSessionID);
  574. switch(pContext->pKeyExchInfo->Spec)
  575. {
  576. case SP_EXCH_RSA_PKCS1:
  577. if((pZombie->fProtocol & SP_PROT_CLIENTS) || !pZombie->hMasterProv)
  578. {
  579. pZombie->hMasterProv = g_hRsaSchannel;
  580. }
  581. break;
  582. case SP_EXCH_DH_PKCS3:
  583. if((pZombie->fProtocol & SP_PROT_CLIENTS) || !pZombie->hMasterProv)
  584. {
  585. pZombie->hMasterProv = g_hDhSchannelProv;
  586. }
  587. break;
  588. default:
  589. Status = SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  590. goto cleanup;
  591. }
  592. pContext->hReadProv = pZombie->hMasterProv;
  593. pContext->hWriteProv = pZombie->hMasterProv;
  594. pbBuffer += TAG_LENGTH + pTag->Length;
  595. //
  596. // Extract optional serialized data.
  597. //
  598. fDone = FALSE;
  599. while(!fDone)
  600. {
  601. DWORD Type = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->Type;
  602. DWORD Length = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->Length;
  603. DWORD DataLength = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->DataLength;
  604. pbBuffer += TAG_LENGTH;
  605. switch(Type)
  606. {
  607. case SslEndOfBuffer:
  608. DebugLog((DEB_TRACE, "SslEndOfBuffer\n"));
  609. fDone = TRUE;
  610. break;
  611. case SslReadKey:
  612. DebugLog((DEB_TRACE, "SslReadKey\n"));
  613. if(!CryptImportKey(pZombie->hMasterProv,
  614. pbBuffer,
  615. DataLength,
  616. 0, 0,
  617. &pContext->hReadKey))
  618. {
  619. SP_LOG_RESULT(GetLastError());
  620. Status = PCT_INT_INTERNAL_ERROR;
  621. goto cleanup;
  622. }
  623. DebugLog((DEB_TRACE, "Key:0x%p\n", pContext->hReadKey));
  624. break;
  625. case SslReadMac:
  626. DebugLog((DEB_TRACE, "SslReadMac\n"));
  627. if(!CryptImportKey(pZombie->hMasterProv,
  628. pbBuffer,
  629. DataLength,
  630. 0, 0,
  631. &pContext->hReadMAC))
  632. {
  633. SP_LOG_RESULT(GetLastError());
  634. Status = PCT_INT_INTERNAL_ERROR;
  635. goto cleanup;
  636. }
  637. break;
  638. case SslWriteKey:
  639. DebugLog((DEB_TRACE, "SslWriteKey\n"));
  640. if(!CryptImportKey(pZombie->hMasterProv,
  641. pbBuffer,
  642. DataLength,
  643. 0, 0,
  644. &pContext->hWriteKey))
  645. {
  646. SP_LOG_RESULT(GetLastError());
  647. Status = PCT_INT_INTERNAL_ERROR;
  648. goto cleanup;
  649. }
  650. DebugLog((DEB_TRACE, "Key:0x%p\n", pContext->hWriteKey));
  651. break;
  652. case SslWriteMac:
  653. DebugLog((DEB_TRACE, "SslWriteMac\n"));
  654. if(!CryptImportKey(pZombie->hMasterProv,
  655. pbBuffer,
  656. DataLength,
  657. 0, 0,
  658. &pContext->hWriteMAC))
  659. {
  660. SP_LOG_RESULT(GetLastError());
  661. Status = PCT_INT_INTERNAL_ERROR;
  662. goto cleanup;
  663. }
  664. break;
  665. case SslMapper:
  666. DebugLog((DEB_TRACE, "SslMapper\n"));
  667. pZombie->phMapper = *(HMAPPER **)pbBuffer;
  668. break;
  669. case SslRemoteCertificate:
  670. DebugLog((DEB_TRACE, "SslRemoteCertificate\n"));
  671. // Save a pointer to the serialized certificate context
  672. // of the remote certificate. This will be deserialized
  673. // by the QueryContextAttribute function when the
  674. // application asks for it.
  675. pZombie->pbServerCertificate = SPExternalAlloc(Length);
  676. if(pZombie->pbServerCertificate)
  677. {
  678. memcpy(pZombie->pbServerCertificate, pbBuffer, Length);
  679. pZombie->cbServerCertificate = Length;
  680. }
  681. break;
  682. default:
  683. DebugLog((DEB_WARN, "Invalid tag %d found when deserializing context buffer\n"));
  684. Status = PCT_INT_INTERNAL_ERROR;
  685. goto cleanup;
  686. }
  687. pbBuffer += Length;
  688. }
  689. *ppContext = pContext;
  690. pContext = NULL;
  691. Status = PCT_ERR_OK;
  692. cleanup:
  693. if(pContext != NULL)
  694. {
  695. LsaContextDelete(pContext);
  696. SPExternalFree(pContext);
  697. }
  698. return Status;
  699. }