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
819 lines
24 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 2000.
|
|
//
|
|
// File: serial.c
|
|
//
|
|
// Contents: Schannel context serialization routines.
|
|
//
|
|
// Functions: SPContextSerialize
|
|
// SPContextDeserialize
|
|
//
|
|
// History: 02-15-00 jbanes Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <spbase.h>
|
|
#include <certmap.h>
|
|
#include <mapper.h>
|
|
#include <align.h>
|
|
|
|
typedef enum _SERIALIZED_ITEM_TYPE
|
|
{
|
|
SslEndOfBuffer = 0,
|
|
SslContext,
|
|
SslReadKey,
|
|
SslReadMac,
|
|
SslWriteKey,
|
|
SslWriteMac,
|
|
SslMapper,
|
|
SslRemoteCertificate
|
|
} SERIALIZED_ITEM_TYPE;
|
|
|
|
typedef struct _SERIALIZED_ITEM_TAG
|
|
{
|
|
DWORD Type;
|
|
DWORD Length;
|
|
DWORD DataLength;
|
|
DWORD reserved;
|
|
} SERIALIZED_ITEM_TAG;
|
|
|
|
#define TAG_LENGTH sizeof(SERIALIZED_ITEM_TAG)
|
|
|
|
|
|
DWORD
|
|
GetSerializedKeyLength(
|
|
HCRYPTKEY hKey)
|
|
{
|
|
DWORD cbKey;
|
|
|
|
if(!CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, NULL, &cbKey))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
return 0;
|
|
}
|
|
|
|
return ROUND_UP_COUNT(TAG_LENGTH + cbKey, ALIGN_LPVOID);
|
|
}
|
|
|
|
|
|
SP_STATUS
|
|
SerializeKey(
|
|
HCRYPTKEY hKey,
|
|
SERIALIZED_ITEM_TYPE Type,
|
|
PBYTE pbBuffer,
|
|
PDWORD pcbBuffer)
|
|
{
|
|
SERIALIZED_ITEM_TAG *pTag;
|
|
PBYTE pbKey;
|
|
DWORD cbKey;
|
|
|
|
if(*pcbBuffer <= TAG_LENGTH)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
|
|
pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
|
|
|
|
pbKey = pbBuffer + TAG_LENGTH;
|
|
cbKey = *pcbBuffer - TAG_LENGTH;
|
|
|
|
if(!CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, pbKey, &cbKey))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
return PCT_INT_INTERNAL_ERROR;
|
|
}
|
|
|
|
pTag->Type = Type;
|
|
pTag->Length = ROUND_UP_COUNT(cbKey, ALIGN_LPVOID);
|
|
pTag->DataLength = cbKey;
|
|
|
|
if(*pcbBuffer <= TAG_LENGTH + pTag->Length)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
|
|
*pcbBuffer = TAG_LENGTH + pTag->Length;
|
|
|
|
return PCT_ERR_OK;
|
|
}
|
|
|
|
|
|
SP_STATUS
|
|
SerializeContext(
|
|
PSPContext pContext,
|
|
SERIALIZE_LOCATOR_FN LocatorMove,
|
|
PBYTE pbBuffer,
|
|
PDWORD pcbBuffer,
|
|
BOOL fDestroyKeys)
|
|
{
|
|
DWORD cbData;
|
|
DWORD cbBuffer;
|
|
DWORD cbBytesNeeded;
|
|
SERIALIZED_ITEM_TAG *pTag;
|
|
PSessCacheItem pZombie;
|
|
SP_STATUS pctRet;
|
|
|
|
//
|
|
// Initialize buffer pointers.
|
|
//
|
|
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer = 0;
|
|
}
|
|
else
|
|
{
|
|
cbBuffer = *pcbBuffer;
|
|
}
|
|
|
|
pZombie = pContext->RipeZombie;
|
|
|
|
|
|
//
|
|
// Context structure.
|
|
//
|
|
|
|
cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + sizeof(SPPackedContext),
|
|
ALIGN_LPVOID);
|
|
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += cbBytesNeeded;
|
|
}
|
|
else
|
|
{
|
|
PSPPackedContext pSerialContext;
|
|
HLOCATOR hLocator;
|
|
|
|
if(cbBuffer < cbBytesNeeded)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
|
|
pContext->Flags |= CONTEXT_FLAG_SERIALIZED;
|
|
|
|
pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
|
|
pSerialContext = (PSPPackedContext)(pbBuffer + TAG_LENGTH);
|
|
|
|
pTag->Type = SslContext;
|
|
pTag->Length = cbBytesNeeded - TAG_LENGTH;
|
|
|
|
pSerialContext->Magic = pContext->Magic;
|
|
pSerialContext->State = pContext->State;
|
|
pSerialContext->Flags = pContext->Flags;
|
|
pSerialContext->dwProtocol = pContext->dwProtocol;
|
|
|
|
pSerialContext->ContextThumbprint = pContext->ContextThumbprint;
|
|
|
|
pSerialContext->dwCipherInfo = (DWORD)(pContext->pCipherInfo - g_AvailableCiphers);
|
|
pSerialContext->dwHashInfo = (DWORD)(pContext->pHashInfo - g_AvailableHashes);
|
|
pSerialContext->dwKeyExchInfo = (DWORD)(pContext->pKeyExchInfo - g_AvailableExch);
|
|
|
|
pSerialContext->dwExchStrength = pContext->RipeZombie->dwExchStrength;
|
|
|
|
pSerialContext->ReadCounter = pContext->ReadCounter;
|
|
pSerialContext->WriteCounter = pContext->WriteCounter;
|
|
|
|
if(pZombie->fProtocol & SP_PROT_SERVERS)
|
|
{
|
|
if(pZombie->pActiveServerCred)
|
|
{
|
|
#ifdef _WIN64
|
|
pSerialContext->hMasterProv.QuadPart = (ULONGLONG)pZombie->pActiveServerCred->hRemoteProv;
|
|
#else
|
|
pSerialContext->hMasterProv.LowPart = (DWORD)pZombie->pActiveServerCred->hRemoteProv;
|
|
#endif
|
|
}
|
|
|
|
// Copy the locator.
|
|
if(pZombie->phMapper && pZombie->hLocator && LocatorMove)
|
|
{
|
|
LocatorMove(pZombie->hLocator, &hLocator);
|
|
|
|
#ifdef _WIN64
|
|
pSerialContext->hLocator.QuadPart = (ULONGLONG)hLocator;
|
|
#else
|
|
pSerialContext->hLocator.LowPart = (DWORD)hLocator;
|
|
#endif
|
|
}
|
|
|
|
pSerialContext->LocatorStatus = pZombie->LocatorStatus;
|
|
}
|
|
|
|
pSerialContext->cbSessionID = pZombie->cbSessionID;
|
|
memcpy(pSerialContext->SessionID, pZombie->SessionID, pZombie->cbSessionID);
|
|
|
|
pbBuffer += cbBytesNeeded;
|
|
cbBuffer -= cbBytesNeeded;
|
|
}
|
|
|
|
|
|
//
|
|
// Certificate mapper structure.
|
|
//
|
|
|
|
if(pContext->RipeZombie->phMapper)
|
|
{
|
|
cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + sizeof(PVOID),
|
|
ALIGN_LPVOID);
|
|
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += cbBytesNeeded;
|
|
}
|
|
else
|
|
{
|
|
if(cbBuffer < cbBytesNeeded)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
|
|
pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
|
|
|
|
pTag->Type = SslMapper;
|
|
pTag->Length = cbBytesNeeded - TAG_LENGTH;
|
|
|
|
CopyMemory(pbBuffer + TAG_LENGTH,
|
|
&pZombie->phMapper->m_Reserved1,
|
|
sizeof(PVOID));
|
|
|
|
pbBuffer += cbBytesNeeded;
|
|
cbBuffer -= cbBytesNeeded;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Data encryption and MAC keys.
|
|
//
|
|
|
|
if(pContext->pCipherInfo->aiCipher != CALG_NULLCIPHER)
|
|
{
|
|
// Read key.
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += GetSerializedKeyLength(pContext->hReadKey);
|
|
}
|
|
else
|
|
{
|
|
cbData = cbBuffer;
|
|
pctRet = SerializeKey(pContext->hReadKey,
|
|
SslReadKey,
|
|
pbBuffer,
|
|
&cbData);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return pctRet;
|
|
}
|
|
if(fDestroyKeys)
|
|
{
|
|
if(!CryptDestroyKey(pContext->hReadKey))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
}
|
|
pContext->hReadKey = 0;
|
|
}
|
|
|
|
pbBuffer += cbData;
|
|
cbBuffer -= cbData;
|
|
}
|
|
|
|
// Write key.
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += GetSerializedKeyLength(pContext->hWriteKey);
|
|
}
|
|
else
|
|
{
|
|
cbData = cbBuffer;
|
|
pctRet = SerializeKey(pContext->hWriteKey,
|
|
SslWriteKey,
|
|
pbBuffer,
|
|
&cbData);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return pctRet;
|
|
}
|
|
if(fDestroyKeys)
|
|
{
|
|
if(!CryptDestroyKey(pContext->hWriteKey))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
}
|
|
pContext->hWriteKey = 0;
|
|
}
|
|
|
|
pbBuffer += cbData;
|
|
cbBuffer -= cbData;
|
|
}
|
|
}
|
|
|
|
// Read MAC.
|
|
if(pContext->hReadMAC)
|
|
{
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += GetSerializedKeyLength(pContext->hReadMAC);
|
|
}
|
|
else
|
|
{
|
|
cbData = cbBuffer;
|
|
pctRet = SerializeKey(pContext->hReadMAC,
|
|
SslReadMac,
|
|
pbBuffer,
|
|
&cbData);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return pctRet;
|
|
}
|
|
|
|
pbBuffer += cbData;
|
|
cbBuffer -= cbData;
|
|
}
|
|
}
|
|
|
|
// Write MAC.
|
|
if(pContext->hWriteMAC)
|
|
{
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += GetSerializedKeyLength(pContext->hWriteMAC);
|
|
}
|
|
else
|
|
{
|
|
cbData = cbBuffer;
|
|
pctRet = SerializeKey(pContext->hWriteMAC,
|
|
SslWriteMac,
|
|
pbBuffer,
|
|
&cbData);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return pctRet;
|
|
}
|
|
|
|
pbBuffer += cbData;
|
|
cbBuffer -= cbData;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Remote certificate.
|
|
//
|
|
|
|
if(pContext->RipeZombie->pRemoteCert)
|
|
{
|
|
if(pbBuffer == NULL)
|
|
{
|
|
pctRet = SerializeCertContext(pContext->RipeZombie->pRemoteCert,
|
|
NULL,
|
|
&cbData);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return SP_LOG_RESULT(pctRet);
|
|
}
|
|
|
|
cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + cbData, ALIGN_LPVOID);
|
|
|
|
cbBuffer += cbBytesNeeded;
|
|
}
|
|
else
|
|
{
|
|
if(cbBuffer < TAG_LENGTH)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
cbData = cbBuffer - TAG_LENGTH;
|
|
|
|
pctRet = SerializeCertContext(pContext->RipeZombie->pRemoteCert,
|
|
pbBuffer + TAG_LENGTH,
|
|
&cbData);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return SP_LOG_RESULT(pctRet);
|
|
}
|
|
|
|
cbBytesNeeded = ROUND_UP_COUNT(TAG_LENGTH + cbData, ALIGN_LPVOID);
|
|
|
|
pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
|
|
|
|
pTag->Type = SslRemoteCertificate;
|
|
pTag->Length = cbBytesNeeded - TAG_LENGTH;
|
|
|
|
pbBuffer += cbBytesNeeded;
|
|
cbBuffer -= cbBytesNeeded;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// End of buffer marker.
|
|
//
|
|
|
|
if(pbBuffer == NULL)
|
|
{
|
|
cbBuffer += TAG_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
if(cbBuffer < TAG_LENGTH)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
|
|
pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
|
|
|
|
pTag->Type = SslEndOfBuffer;
|
|
pTag->Length = 0;
|
|
|
|
pbBuffer += TAG_LENGTH;
|
|
cbBuffer -= TAG_LENGTH;
|
|
}
|
|
|
|
if(pbBuffer == NULL)
|
|
{
|
|
*pcbBuffer = cbBuffer;
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
if(cbBuffer)
|
|
{
|
|
DebugLog((DEB_WARN, "%d bytes left over when serializing context.\n", cbBuffer));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return PCT_ERR_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SPContextSerialize
|
|
//
|
|
// Synopsis: Extract out everything necessary for bulk data encryption
|
|
// from an Schannel context, and place it in a linear buffer.
|
|
//
|
|
// Arguments: [pCred] -- Context to be serialized.
|
|
// [ppBuffer] -- Destination buffer.
|
|
// [pcbBuffer] -- Destination buffer length.
|
|
//
|
|
// History: 09-25-96 jbanes Hacked for LSA integration.
|
|
//
|
|
// Notes: This routine is called by the LSA process when transitioning
|
|
// from the handshaking phase to the bulk encryption phase.
|
|
//
|
|
// This function is also called by the application process as
|
|
// part of ExportSecurityContext.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
SP_STATUS
|
|
SPContextSerialize(
|
|
PSPContext pContext,
|
|
SERIALIZE_LOCATOR_FN LocatorMove,
|
|
PBYTE * ppBuffer,
|
|
PDWORD pcbBuffer,
|
|
BOOL fDestroyKeys)
|
|
{
|
|
PBYTE pbBuffer;
|
|
DWORD cbBuffer;
|
|
SP_STATUS pctRet;
|
|
|
|
// Determine size of serialized buffer.
|
|
pctRet = SerializeContext(pContext, LocatorMove, NULL, &cbBuffer, fDestroyKeys);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
return SP_LOG_RESULT(pctRet);
|
|
}
|
|
|
|
// Allocate memory for serialized buffer.
|
|
pbBuffer = SPExternalAlloc(cbBuffer);
|
|
if(pbBuffer == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
// Generate serialized context.
|
|
pctRet = SerializeContext(pContext, LocatorMove, pbBuffer, &cbBuffer, fDestroyKeys);
|
|
if(pctRet != PCT_ERR_OK)
|
|
{
|
|
SPExternalFree(pbBuffer);
|
|
return SP_LOG_RESULT(pctRet);
|
|
}
|
|
|
|
// Set outputs
|
|
*ppBuffer = pbBuffer;
|
|
*pcbBuffer = cbBuffer;
|
|
|
|
return PCT_ERR_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SPContextDeserialize
|
|
//
|
|
// Synopsis: Build an Schannel context structure from a linear buffer,
|
|
// which was created via SPContextSerialize by the other
|
|
// process.
|
|
//
|
|
// Arguments: [pBuffer] -- Buffer containing serialized context.
|
|
// The new context structure is built over
|
|
// the top of this buffer.
|
|
//
|
|
// History: 09-25-96 jbanes Hacked for LSA integration.
|
|
//
|
|
// Notes: This routine is called by the application process when
|
|
// transitioning from the handshaking phase to the bulk
|
|
// encryption phase.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
SP_STATUS
|
|
SPContextDeserialize(
|
|
PBYTE pbBuffer,
|
|
PSPContext *ppContext)
|
|
{
|
|
PSPContext pContext = NULL;
|
|
DWORD Status = PCT_INT_INTERNAL_ERROR;
|
|
BOOL fDone;
|
|
PSPPackedContext pSerialContext;
|
|
PSessCacheItem pZombie;
|
|
SERIALIZED_ITEM_TAG *pTag;
|
|
DWORD cbContext;
|
|
|
|
DebugLog((DEB_TRACE, "Deserialize context\n"));
|
|
|
|
//
|
|
// Extract serialized context.
|
|
//
|
|
|
|
pTag = (SERIALIZED_ITEM_TAG *)pbBuffer;
|
|
|
|
if(pTag->Type != SslContext)
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
|
|
}
|
|
if(pTag->Length < sizeof(PSPPackedContext))
|
|
{
|
|
return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
|
|
}
|
|
|
|
pSerialContext = (PSPPackedContext)(pbBuffer + TAG_LENGTH);
|
|
|
|
cbContext = ROUND_UP_COUNT(sizeof(SPContext), ALIGN_LPVOID);
|
|
|
|
pContext = SPExternalAlloc(cbContext + sizeof(SessCacheItem));
|
|
if(pContext == NULL)
|
|
{
|
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
pContext->RipeZombie = (PSessCacheItem)((PBYTE)pContext + cbContext);
|
|
pZombie = pContext->RipeZombie;
|
|
|
|
pContext->Magic = pSerialContext->Magic;
|
|
pContext->State = pSerialContext->State;
|
|
pContext->Flags = pSerialContext->Flags;
|
|
pContext->dwProtocol = pSerialContext->dwProtocol;
|
|
|
|
pContext->ContextThumbprint = pSerialContext->ContextThumbprint;
|
|
|
|
pContext->pCipherInfo = g_AvailableCiphers + pSerialContext->dwCipherInfo;
|
|
pContext->pHashInfo = g_AvailableHashes + pSerialContext->dwHashInfo;
|
|
pContext->pKeyExchInfo = g_AvailableExch + pSerialContext->dwKeyExchInfo;
|
|
|
|
pContext->pReadCipherInfo = pContext->pCipherInfo;
|
|
pContext->pWriteCipherInfo = pContext->pCipherInfo;
|
|
pContext->pReadHashInfo = pContext->pHashInfo;
|
|
pContext->pWriteHashInfo = pContext->pHashInfo;
|
|
|
|
pContext->ReadCounter = pSerialContext->ReadCounter;
|
|
pContext->WriteCounter = pSerialContext->WriteCounter;
|
|
|
|
pContext->InitiateHello = GenerateHello;
|
|
|
|
switch(pContext->dwProtocol)
|
|
{
|
|
case SP_PROT_PCT1_CLIENT:
|
|
pContext->Decrypt = Pct1DecryptMessage;
|
|
pContext->Encrypt = Pct1EncryptMessage;
|
|
pContext->ProtocolHandler = Pct1ClientProtocolHandler;
|
|
pContext->DecryptHandler = Pct1DecryptHandler;
|
|
pContext->GetHeaderSize = Pct1GetHeaderSize;
|
|
break;
|
|
|
|
case SP_PROT_PCT1_SERVER:
|
|
pContext->Decrypt = Pct1DecryptMessage;
|
|
pContext->Encrypt = Pct1EncryptMessage;
|
|
pContext->ProtocolHandler = Pct1ServerProtocolHandler;
|
|
pContext->DecryptHandler = Pct1DecryptHandler;
|
|
pContext->GetHeaderSize = Pct1GetHeaderSize;
|
|
break;
|
|
|
|
case SP_PROT_SSL2_CLIENT:
|
|
pContext->Decrypt = Ssl2DecryptMessage;
|
|
pContext->Encrypt = Ssl2EncryptMessage;
|
|
pContext->ProtocolHandler = Ssl2ClientProtocolHandler;
|
|
pContext->DecryptHandler = Ssl2DecryptHandler;
|
|
pContext->GetHeaderSize = Ssl2GetHeaderSize;
|
|
break;
|
|
|
|
case SP_PROT_SSL2_SERVER:
|
|
pContext->Decrypt = Ssl2DecryptMessage;
|
|
pContext->Encrypt = Ssl2EncryptMessage;
|
|
pContext->ProtocolHandler = Ssl2ServerProtocolHandler;
|
|
pContext->DecryptHandler = Ssl2DecryptHandler;
|
|
pContext->GetHeaderSize = Ssl2GetHeaderSize;
|
|
break;
|
|
|
|
case SP_PROT_SSL3_CLIENT:
|
|
case SP_PROT_SSL3_SERVER:
|
|
case SP_PROT_TLS1_CLIENT:
|
|
case SP_PROT_TLS1_SERVER:
|
|
pContext->Decrypt = Ssl3DecryptMessage;
|
|
pContext->Encrypt = Ssl3EncryptMessage;
|
|
pContext->ProtocolHandler = Ssl3ProtocolHandler;
|
|
pContext->DecryptHandler = Ssl3DecryptHandler;
|
|
pContext->GetHeaderSize = Ssl3GetHeaderSize;
|
|
break;
|
|
|
|
default:
|
|
pContext->Decrypt = NULL;
|
|
pContext->Encrypt = NULL;
|
|
pContext->ProtocolHandler = NULL;
|
|
pContext->DecryptHandler = NULL;
|
|
pContext->GetHeaderSize = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Extract serialized cache entry.
|
|
//
|
|
|
|
pZombie->fProtocol = pSerialContext->dwProtocol;
|
|
pZombie->dwExchStrength = pSerialContext->dwExchStrength;
|
|
|
|
#ifdef _WIN64
|
|
pZombie->hLocator = (HLOCATOR)pSerialContext->hLocator.QuadPart;
|
|
pZombie->hMasterProv = (HCRYPTPROV)pSerialContext->hMasterProv.QuadPart;
|
|
#else
|
|
pZombie->hLocator = (HLOCATOR)pSerialContext->hLocator.LowPart;
|
|
pZombie->hMasterProv = (HCRYPTPROV)pSerialContext->hMasterProv.LowPart;
|
|
#endif
|
|
pZombie->LocatorStatus = pSerialContext->LocatorStatus;
|
|
|
|
pZombie->cbSessionID = pSerialContext->cbSessionID;
|
|
memcpy(pZombie->SessionID, pSerialContext->SessionID, pSerialContext->cbSessionID);
|
|
|
|
switch(pContext->pKeyExchInfo->Spec)
|
|
{
|
|
case SP_EXCH_RSA_PKCS1:
|
|
if((pZombie->fProtocol & SP_PROT_CLIENTS) || !pZombie->hMasterProv)
|
|
{
|
|
pZombie->hMasterProv = g_hRsaSchannel;
|
|
}
|
|
break;
|
|
|
|
case SP_EXCH_DH_PKCS3:
|
|
if((pZombie->fProtocol & SP_PROT_CLIENTS) || !pZombie->hMasterProv)
|
|
{
|
|
pZombie->hMasterProv = g_hDhSchannelProv;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Status = SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
|
|
goto cleanup;
|
|
}
|
|
pContext->hReadProv = pZombie->hMasterProv;
|
|
pContext->hWriteProv = pZombie->hMasterProv;
|
|
|
|
pbBuffer += TAG_LENGTH + pTag->Length;
|
|
|
|
|
|
//
|
|
// Extract optional serialized data.
|
|
//
|
|
|
|
fDone = FALSE;
|
|
|
|
while(!fDone)
|
|
{
|
|
DWORD Type = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->Type;
|
|
DWORD Length = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->Length;
|
|
DWORD DataLength = ((SERIALIZED_ITEM_TAG UNALIGNED *)pbBuffer)->DataLength;
|
|
|
|
pbBuffer += TAG_LENGTH;
|
|
|
|
switch(Type)
|
|
{
|
|
case SslEndOfBuffer:
|
|
DebugLog((DEB_TRACE, "SslEndOfBuffer\n"));
|
|
fDone = TRUE;
|
|
break;
|
|
|
|
case SslReadKey:
|
|
DebugLog((DEB_TRACE, "SslReadKey\n"));
|
|
if(!CryptImportKey(pZombie->hMasterProv,
|
|
pbBuffer,
|
|
DataLength,
|
|
0, 0,
|
|
&pContext->hReadKey))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
Status = PCT_INT_INTERNAL_ERROR;
|
|
goto cleanup;
|
|
}
|
|
DebugLog((DEB_TRACE, "Key:0x%p\n", pContext->hReadKey));
|
|
break;
|
|
|
|
case SslReadMac:
|
|
DebugLog((DEB_TRACE, "SslReadMac\n"));
|
|
if(!CryptImportKey(pZombie->hMasterProv,
|
|
pbBuffer,
|
|
DataLength,
|
|
0, 0,
|
|
&pContext->hReadMAC))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
Status = PCT_INT_INTERNAL_ERROR;
|
|
goto cleanup;
|
|
}
|
|
break;
|
|
|
|
case SslWriteKey:
|
|
DebugLog((DEB_TRACE, "SslWriteKey\n"));
|
|
if(!CryptImportKey(pZombie->hMasterProv,
|
|
pbBuffer,
|
|
DataLength,
|
|
0, 0,
|
|
&pContext->hWriteKey))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
Status = PCT_INT_INTERNAL_ERROR;
|
|
goto cleanup;
|
|
}
|
|
DebugLog((DEB_TRACE, "Key:0x%p\n", pContext->hWriteKey));
|
|
break;
|
|
|
|
case SslWriteMac:
|
|
DebugLog((DEB_TRACE, "SslWriteMac\n"));
|
|
if(!CryptImportKey(pZombie->hMasterProv,
|
|
pbBuffer,
|
|
DataLength,
|
|
0, 0,
|
|
&pContext->hWriteMAC))
|
|
{
|
|
SP_LOG_RESULT(GetLastError());
|
|
Status = PCT_INT_INTERNAL_ERROR;
|
|
goto cleanup;
|
|
}
|
|
break;
|
|
|
|
case SslMapper:
|
|
DebugLog((DEB_TRACE, "SslMapper\n"));
|
|
pZombie->phMapper = *(HMAPPER **)pbBuffer;
|
|
break;
|
|
|
|
case SslRemoteCertificate:
|
|
DebugLog((DEB_TRACE, "SslRemoteCertificate\n"));
|
|
// Save a pointer to the serialized certificate context
|
|
// of the remote certificate. This will be deserialized
|
|
// by the QueryContextAttribute function when the
|
|
// application asks for it.
|
|
pZombie->pbServerCertificate = SPExternalAlloc(Length);
|
|
if(pZombie->pbServerCertificate)
|
|
{
|
|
memcpy(pZombie->pbServerCertificate, pbBuffer, Length);
|
|
pZombie->cbServerCertificate = Length;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DebugLog((DEB_WARN, "Invalid tag %d found when deserializing context buffer\n"));
|
|
Status = PCT_INT_INTERNAL_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
pbBuffer += Length;
|
|
}
|
|
|
|
*ppContext = pContext;
|
|
pContext = NULL;
|
|
|
|
Status = PCT_ERR_OK;
|
|
|
|
cleanup:
|
|
|
|
if(pContext != NULL)
|
|
{
|
|
LsaContextDelete(pContext);
|
|
SPExternalFree(pContext);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|