686 lines
18 KiB
C
686 lines
18 KiB
C
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
||
|
//
|
||
|
// File: pickle.c
|
||
|
//
|
||
|
// Contents:
|
||
|
//
|
||
|
// Classes:
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// History: 8-02-95 RichardW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <spbase.h>
|
||
|
#include <ssl2msg.h>
|
||
|
|
||
|
#define SSL_OFFSET_OF(t, v) ((DWORD)(ULONG_PTR)&(((t)NULL)->v))
|
||
|
|
||
|
|
||
|
|
||
|
#define SIZEOF(pMessage) (SslRecordSize((PSSL2_MESSAGE_HEADER) pMessage ) )
|
||
|
|
||
|
DWORD
|
||
|
SslRecordSize(
|
||
|
PSSL2_MESSAGE_HEADER pHeader)
|
||
|
{
|
||
|
DWORD Size;
|
||
|
|
||
|
if (pHeader->Byte0 & 0x80)
|
||
|
{
|
||
|
Size = COMBINEBYTES(pHeader->Byte0, pHeader->Byte1) & 0x7FFF;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Size = COMBINEBYTES(pHeader->Byte0, pHeader->Byte1) & 0x3FFF;
|
||
|
}
|
||
|
return(Size);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
Ssl2MapCipherToExternal(
|
||
|
Ssl2_Cipher_Kind FastForm,
|
||
|
PSsl2_Cipher_Tuple pTuple)
|
||
|
{
|
||
|
pTuple->C1 = (UCHAR)((FastForm >> 16) & 0xff);
|
||
|
pTuple->C2 = (UCHAR)((FastForm >> 8) & 0xff);
|
||
|
pTuple->C3 = (UCHAR)(FastForm & 0xff);
|
||
|
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
Ssl2_Cipher_Kind
|
||
|
Ssl2MapCipherFromExternal(
|
||
|
PSsl2_Cipher_Tuple pTuple)
|
||
|
{
|
||
|
|
||
|
return SSL_MKFAST(pTuple->C1, pTuple->C2, pTuple->C3);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
SP_STATUS
|
||
|
Ssl2PackClientHello(
|
||
|
PSsl2_Client_Hello pCanonical,
|
||
|
PSPBuffer pCommOutput)
|
||
|
{
|
||
|
DWORD cbMessage;
|
||
|
PSSL2_CLIENT_HELLO pMessage;
|
||
|
DWORD Size;
|
||
|
PUCHAR pBuffer;
|
||
|
DWORD i;
|
||
|
|
||
|
if(pCanonical == NULL || pCommOutput == NULL)
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
|
||
|
}
|
||
|
|
||
|
pCommOutput->cbData = 0;
|
||
|
|
||
|
pCommOutput->cbData = pCanonical->cbSessionID +
|
||
|
pCanonical->cbChallenge +
|
||
|
pCanonical->cCipherSpecs * sizeof(Ssl2_Cipher_Tuple) +
|
||
|
SSL_OFFSET_OF(PSSL2_CLIENT_HELLO, VariantData);
|
||
|
|
||
|
cbMessage = pCommOutput->cbData - sizeof(SSL2_MESSAGE_HEADER);
|
||
|
|
||
|
/* are we allocating our own memory? */
|
||
|
if(pCommOutput->pvBuffer == NULL)
|
||
|
{
|
||
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
||
|
if (NULL == pCommOutput->pvBuffer)
|
||
|
{
|
||
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
||
|
}
|
||
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
||
|
}
|
||
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
||
|
{
|
||
|
// Required buffer size returned in pCommOutput->cbData.
|
||
|
return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
|
||
|
}
|
||
|
|
||
|
pMessage = pCommOutput->pvBuffer;
|
||
|
|
||
|
pMessage->MessageId = SSL2_MT_CLIENT_HELLO;
|
||
|
|
||
|
pMessage->VersionMsb = MSBOF(pCanonical->dwVer);
|
||
|
pMessage->VersionLsb = LSBOF(pCanonical->dwVer);
|
||
|
|
||
|
pBuffer = pMessage->VariantData;
|
||
|
|
||
|
cbMessage -= pCanonical->cCipherSpecs * sizeof(Ssl2_Cipher_Tuple);
|
||
|
pCommOutput->cbData -= pCanonical->cCipherSpecs * sizeof(Ssl2_Cipher_Tuple);
|
||
|
|
||
|
Size = 0;
|
||
|
|
||
|
for (i = 0; i < pCanonical->cCipherSpecs ; i++ )
|
||
|
{
|
||
|
if (!Ssl2MapCipherToExternal(pCanonical->CipherSpecs[i],
|
||
|
(PSsl2_Cipher_Tuple) pBuffer) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
pBuffer += sizeof(Ssl2_Cipher_Tuple);
|
||
|
Size += sizeof(Ssl2_Cipher_Tuple);
|
||
|
}
|
||
|
|
||
|
cbMessage += Size;
|
||
|
pCommOutput->cbData += Size;
|
||
|
|
||
|
pCommOutput->cbData = cbMessage + 2;
|
||
|
|
||
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
||
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
||
|
|
||
|
pMessage->CipherSpecsLenMsb = MSBOF(Size);
|
||
|
pMessage->CipherSpecsLenLsb = LSBOF(Size);
|
||
|
|
||
|
pMessage->SessionIdLenMsb = MSBOF(pCanonical->cbSessionID);
|
||
|
pMessage->SessionIdLenLsb = LSBOF(pCanonical->cbSessionID);
|
||
|
if (pCanonical->cbSessionID)
|
||
|
{
|
||
|
CopyMemory( pBuffer,
|
||
|
pCanonical->SessionID,
|
||
|
pCanonical->cbSessionID);
|
||
|
|
||
|
pBuffer += pCanonical->cbSessionID;
|
||
|
}
|
||
|
|
||
|
pMessage->ChallengeLenMsb = MSBOF(pCanonical->cbChallenge);
|
||
|
pMessage->ChallengeLenLsb = LSBOF(pCanonical->cbChallenge);
|
||
|
if (pCanonical->cbChallenge)
|
||
|
{
|
||
|
CopyMemory( pBuffer,
|
||
|
pCanonical->Challenge,
|
||
|
pCanonical->cbChallenge);
|
||
|
}
|
||
|
|
||
|
return(PCT_ERR_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
SP_STATUS
|
||
|
Ssl2UnpackClientHello(
|
||
|
PSPBuffer pInput,
|
||
|
PSsl2_Client_Hello * ppClient)
|
||
|
{
|
||
|
|
||
|
PSSL2_CLIENT_HELLO pMessage;
|
||
|
DWORD ReportedSize;
|
||
|
DWORD CipherSpecsSize;
|
||
|
DWORD cCipherSpecs;
|
||
|
PSsl2_Client_Hello pCanonical;
|
||
|
PUCHAR pBuffer;
|
||
|
DWORD Size;
|
||
|
DWORD i, dwVer;
|
||
|
|
||
|
pMessage = pInput->pvBuffer;
|
||
|
|
||
|
if(pInput->cbData < 2)
|
||
|
{
|
||
|
pInput->cbData = 2;
|
||
|
return PCT_INT_INCOMPLETE_MSG;
|
||
|
}
|
||
|
|
||
|
ReportedSize = SIZEOF(pMessage);
|
||
|
if ((ReportedSize+2) > pInput->cbData)
|
||
|
{
|
||
|
pInput->cbData = ReportedSize+2;
|
||
|
return PCT_INT_INCOMPLETE_MSG;
|
||
|
}
|
||
|
if(ReportedSize < SSL_OFFSET_OF(PSSL2_CLIENT_HELLO, VariantData))
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
if (pMessage->MessageId != SSL2_MT_CLIENT_HELLO) {
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
dwVer = COMBINEBYTES(pMessage->VersionMsb, pMessage->VersionLsb);
|
||
|
|
||
|
if (dwVer < 2) //VERSION 2 WILL COMPUTE TO 2 (00:02)
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
CipherSpecsSize = COMBINEBYTES( pMessage->CipherSpecsLenMsb,
|
||
|
pMessage->CipherSpecsLenLsb );
|
||
|
|
||
|
|
||
|
*ppClient = NULL;
|
||
|
/* check that this all fits into the message */
|
||
|
if (SSL_OFFSET_OF(PSSL2_CLIENT_HELLO, VariantData)
|
||
|
- sizeof(SSL2_MESSAGE_HEADER) /* don't count the header */
|
||
|
+ CipherSpecsSize
|
||
|
> ReportedSize)
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
cCipherSpecs = CipherSpecsSize / sizeof(Ssl2_Cipher_Tuple);
|
||
|
|
||
|
|
||
|
/* Allocate a buffer for the canonical client hello */
|
||
|
pCanonical = (PSsl2_Client_Hello)SPExternalAlloc(
|
||
|
sizeof(Ssl2_Client_Hello) +
|
||
|
cCipherSpecs * sizeof(UNICipherMap));
|
||
|
|
||
|
if (!pCanonical)
|
||
|
{
|
||
|
return(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
||
|
}
|
||
|
|
||
|
pCanonical->dwVer = COMBINEBYTES( pMessage->VersionMsb,
|
||
|
pMessage->VersionLsb );
|
||
|
|
||
|
pBuffer = pMessage->VariantData;
|
||
|
|
||
|
|
||
|
pCanonical->cCipherSpecs = cCipherSpecs;
|
||
|
|
||
|
for (i = 0 ; i < cCipherSpecs ; i++ )
|
||
|
{
|
||
|
pCanonical->CipherSpecs[i] = Ssl2MapCipherFromExternal((PSsl2_Cipher_Tuple)
|
||
|
pBuffer);
|
||
|
|
||
|
pBuffer += sizeof(Ssl2_Cipher_Tuple);
|
||
|
}
|
||
|
|
||
|
Size = COMBINEBYTES( pMessage->SessionIdLenMsb,
|
||
|
pMessage->SessionIdLenLsb );
|
||
|
|
||
|
if (Size <= SSL2_SESSION_ID_LEN)
|
||
|
{
|
||
|
CopyMemory( pCanonical->SessionID, pBuffer, Size);
|
||
|
pBuffer += Size;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SPExternalFree( pCanonical );
|
||
|
return PCT_ERR_ILLEGAL_MESSAGE;
|
||
|
}
|
||
|
|
||
|
pCanonical->cbSessionID = Size;
|
||
|
|
||
|
Size = COMBINEBYTES( pMessage->ChallengeLenMsb,
|
||
|
pMessage->ChallengeLenLsb );
|
||
|
|
||
|
if ((Size > 0) && (Size <= SSL2_MAX_CHALLENGE_LEN))
|
||
|
{
|
||
|
CopyMemory( pCanonical->Challenge, pBuffer, Size );
|
||
|
|
||
|
pBuffer += Size;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SPExternalFree( pCanonical );
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
pCanonical->cbChallenge = Size;
|
||
|
|
||
|
*ppClient = pCanonical;
|
||
|
pInput->cbData = ReportedSize + sizeof(SSL2_MESSAGE_HEADER);
|
||
|
return( PCT_ERR_OK );
|
||
|
|
||
|
}
|
||
|
|
||
|
SP_STATUS
|
||
|
Ssl2PackServerHello(
|
||
|
PSsl2_Server_Hello pCanonical,
|
||
|
PSPBuffer pCommOutput)
|
||
|
{
|
||
|
DWORD cbMessage;
|
||
|
PSSL2_SERVER_HELLO pMessage;
|
||
|
DWORD Size;
|
||
|
PUCHAR pBuffer;
|
||
|
DWORD i;
|
||
|
|
||
|
if(pCanonical == NULL || pCommOutput == NULL)
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
|
||
|
}
|
||
|
pCommOutput->cbData = 0;
|
||
|
|
||
|
cbMessage = pCanonical->cbConnectionID +
|
||
|
pCanonical->cbCertificate +
|
||
|
pCanonical->cCipherSpecs * sizeof(Ssl2_Cipher_Tuple) +
|
||
|
SSL_OFFSET_OF(PSSL2_SERVER_HELLO, VariantData) -
|
||
|
sizeof(SSL2_MESSAGE_HEADER);
|
||
|
|
||
|
pCommOutput->cbData = cbMessage + 2;
|
||
|
|
||
|
|
||
|
/* are we allocating our own memory? */
|
||
|
if(pCommOutput->pvBuffer == NULL)
|
||
|
{
|
||
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
||
|
if (NULL == pCommOutput->pvBuffer)
|
||
|
{
|
||
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
||
|
}
|
||
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
||
|
}
|
||
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
||
|
{
|
||
|
// Required buffer size returned in pCommOutput->cbData.
|
||
|
return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
|
||
|
}
|
||
|
|
||
|
pMessage = pCommOutput->pvBuffer;
|
||
|
|
||
|
|
||
|
pMessage->MessageId = SSL2_MT_SERVER_HELLO;
|
||
|
pMessage->ServerVersionMsb = SSL2_SERVER_VERSION_MSB;
|
||
|
pMessage->ServerVersionLsb = SSL2_SERVER_VERSION_LSB;
|
||
|
pMessage->SessionIdHit = (UCHAR) pCanonical->SessionIdHit;
|
||
|
pMessage->CertificateType = (UCHAR) pCanonical->CertificateType;
|
||
|
|
||
|
pBuffer = pMessage->VariantData;
|
||
|
|
||
|
//
|
||
|
// Pack certificate if present
|
||
|
//
|
||
|
|
||
|
pMessage->CertificateLenMsb = MSBOF(pCanonical->cbCertificate);
|
||
|
pMessage->CertificateLenLsb = LSBOF(pCanonical->cbCertificate);
|
||
|
|
||
|
if (pCanonical->cbCertificate)
|
||
|
{
|
||
|
CopyMemory( pBuffer,
|
||
|
pCanonical->pCertificate,
|
||
|
pCanonical->cbCertificate);
|
||
|
|
||
|
pBuffer += pCanonical->cbCertificate ;
|
||
|
}
|
||
|
|
||
|
Size = pCanonical->cCipherSpecs * sizeof(Ssl2_Cipher_Tuple);
|
||
|
|
||
|
for (i = 0; i < pCanonical->cCipherSpecs ; i++ )
|
||
|
{
|
||
|
if (Ssl2MapCipherToExternal(pCanonical->pCipherSpecs[i],
|
||
|
(PSsl2_Cipher_Tuple) pBuffer) )
|
||
|
{
|
||
|
pBuffer += sizeof(Ssl2_Cipher_Tuple);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Size -= sizeof(Ssl2_Cipher_Tuple);
|
||
|
cbMessage -= sizeof(Ssl2_Cipher_Tuple);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pCommOutput->cbData = cbMessage + 2;
|
||
|
|
||
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
||
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
||
|
|
||
|
pMessage->CipherSpecsLenMsb = MSBOF(Size);
|
||
|
pMessage->CipherSpecsLenLsb = LSBOF(Size);
|
||
|
|
||
|
pMessage->ConnectionIdLenMsb = MSBOF(pCanonical->cbConnectionID);
|
||
|
pMessage->ConnectionIdLenLsb = LSBOF(pCanonical->cbConnectionID);
|
||
|
if (pCanonical->cbConnectionID)
|
||
|
{
|
||
|
CopyMemory( pBuffer,
|
||
|
pCanonical->ConnectionID,
|
||
|
pCanonical->cbConnectionID);
|
||
|
|
||
|
pBuffer += pCanonical->cbConnectionID;
|
||
|
}
|
||
|
|
||
|
|
||
|
return( PCT_ERR_OK );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
SP_STATUS
|
||
|
Ssl2UnpackServerHello(
|
||
|
PSPBuffer pInput,
|
||
|
PSsl2_Server_Hello * ppServer)
|
||
|
{
|
||
|
PSsl2_Server_Hello pCanonical;
|
||
|
PSSL2_SERVER_HELLO pMessage;
|
||
|
PUCHAR pBuffer;
|
||
|
DWORD cbCertificate;
|
||
|
DWORD cCipherSpecs;
|
||
|
DWORD cbConnId;
|
||
|
DWORD i;
|
||
|
DWORD ReportedSize;
|
||
|
|
||
|
pMessage = pInput->pvBuffer;
|
||
|
if(pInput->cbData < 2)
|
||
|
{
|
||
|
pInput->cbData = 2;
|
||
|
return PCT_INT_INCOMPLETE_MSG;
|
||
|
}
|
||
|
|
||
|
ReportedSize = SIZEOF(pMessage);
|
||
|
if ((ReportedSize+2) > pInput->cbData)
|
||
|
{
|
||
|
pInput->cbData = ReportedSize+2;
|
||
|
return PCT_INT_INCOMPLETE_MSG;
|
||
|
}
|
||
|
|
||
|
|
||
|
if(ReportedSize < SSL_OFFSET_OF(PSSL2_SERVER_HELLO, VariantData) )
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
*ppServer = NULL;
|
||
|
|
||
|
//
|
||
|
// Verify Header:
|
||
|
//
|
||
|
|
||
|
if ((pMessage->MessageId != SSL2_MT_SERVER_HELLO) ||
|
||
|
(pMessage->ServerVersionMsb != SSL2_SERVER_VERSION_MSB) ||
|
||
|
(pMessage->ServerVersionLsb != SSL2_SERVER_VERSION_LSB) )
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
cbCertificate = COMBINEBYTES( pMessage->CertificateLenMsb,
|
||
|
pMessage->CertificateLenLsb);
|
||
|
|
||
|
cCipherSpecs = COMBINEBYTES(pMessage->CipherSpecsLenMsb,
|
||
|
pMessage->CipherSpecsLenLsb);
|
||
|
|
||
|
cCipherSpecs /= sizeof(Ssl2_Cipher_Tuple);
|
||
|
|
||
|
cbConnId = COMBINEBYTES(pMessage->ConnectionIdLenMsb,
|
||
|
pMessage->ConnectionIdLenLsb);
|
||
|
|
||
|
pCanonical = (PSsl2_Server_Hello)SPExternalAlloc(
|
||
|
sizeof(Ssl2_Server_Hello) +
|
||
|
cCipherSpecs * sizeof(Ssl2_Cipher_Kind) +
|
||
|
cbCertificate );
|
||
|
|
||
|
|
||
|
if (!pCanonical)
|
||
|
{
|
||
|
return(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
||
|
}
|
||
|
|
||
|
pCanonical->pCertificate = (PUCHAR) (pCanonical + 1);
|
||
|
pCanonical->pCipherSpecs = (PCipherSpec) (pCanonical + 1);
|
||
|
pCanonical->pCertificate = (PUCHAR) (pCanonical->pCipherSpecs + cCipherSpecs);
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Expand out:
|
||
|
//
|
||
|
|
||
|
pCanonical->SessionIdHit = (DWORD) pMessage->SessionIdHit;
|
||
|
pCanonical->CertificateType = (DWORD) pMessage->CertificateType;
|
||
|
pCanonical->cbCertificate = cbCertificate;
|
||
|
pCanonical->cCipherSpecs = cCipherSpecs;
|
||
|
pCanonical->cbConnectionID = cbConnId;
|
||
|
|
||
|
pBuffer = pMessage->VariantData;
|
||
|
|
||
|
CopyMemory(pCanonical->pCertificate, pBuffer, cbCertificate);
|
||
|
pBuffer += cbCertificate;
|
||
|
|
||
|
for (i = 0 ; i < cCipherSpecs ; i++ )
|
||
|
{
|
||
|
pCanonical->pCipherSpecs[i] = Ssl2MapCipherFromExternal((PSsl2_Cipher_Tuple)
|
||
|
pBuffer);
|
||
|
|
||
|
pBuffer += sizeof(Ssl2_Cipher_Tuple);
|
||
|
}
|
||
|
|
||
|
if ((cbConnId) && (cbConnId <= SSL2_MAX_CONNECTION_ID_LEN))
|
||
|
{
|
||
|
CopyMemory(pCanonical->ConnectionID, pBuffer, cbConnId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SPExternalFree(pCanonical);
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
*ppServer = pCanonical;
|
||
|
pInput->cbData = ReportedSize + sizeof(SSL2_MESSAGE_HEADER);
|
||
|
return( PCT_ERR_OK);
|
||
|
|
||
|
}
|
||
|
|
||
|
SP_STATUS
|
||
|
Ssl2PackClientMasterKey(
|
||
|
PSsl2_Client_Master_Key pCanonical,
|
||
|
PSPBuffer pCommOutput)
|
||
|
{
|
||
|
DWORD cbMessage;
|
||
|
PSSL2_CLIENT_MASTER_KEY pMessage;
|
||
|
PUCHAR pBuffer;
|
||
|
|
||
|
cbMessage = pCanonical->ClearKeyLen +
|
||
|
pCanonical->EncryptedKeyLen +
|
||
|
pCanonical->KeyArgLen +
|
||
|
SSL_OFFSET_OF(PSSL2_CLIENT_MASTER_KEY, VariantData) -
|
||
|
sizeof(SSL2_MESSAGE_HEADER);
|
||
|
|
||
|
pCommOutput->cbData = cbMessage + 2;
|
||
|
|
||
|
/* are we allocating our own memory? */
|
||
|
if(pCommOutput->pvBuffer == NULL)
|
||
|
{
|
||
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
||
|
if (NULL == pCommOutput->pvBuffer)
|
||
|
{
|
||
|
return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
|
||
|
}
|
||
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
||
|
}
|
||
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
||
|
{
|
||
|
// Required buffer size returned in pCommOutput->cbData.
|
||
|
return SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL);
|
||
|
}
|
||
|
pMessage = pCommOutput->pvBuffer;
|
||
|
|
||
|
pBuffer = pMessage->VariantData;
|
||
|
|
||
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
||
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
||
|
|
||
|
pMessage->MessageId = SSL2_MT_CLIENT_MASTER_KEY;
|
||
|
Ssl2MapCipherToExternal(pCanonical->CipherKind, &pMessage->CipherKind);
|
||
|
|
||
|
pMessage->ClearKeyLenMsb = MSBOF(pCanonical->ClearKeyLen);
|
||
|
pMessage->ClearKeyLenLsb = LSBOF(pCanonical->ClearKeyLen);
|
||
|
|
||
|
CopyMemory(pBuffer, pCanonical->ClearKey, pCanonical->ClearKeyLen);
|
||
|
pBuffer += pCanonical->ClearKeyLen;
|
||
|
|
||
|
pMessage->EncryptedKeyLenMsb = MSBOF(pCanonical->EncryptedKeyLen);
|
||
|
pMessage->EncryptedKeyLenLsb = LSBOF(pCanonical->EncryptedKeyLen);
|
||
|
|
||
|
CopyMemory(pBuffer, pCanonical->pbEncryptedKey, pCanonical->EncryptedKeyLen);
|
||
|
pBuffer += pCanonical->EncryptedKeyLen;
|
||
|
|
||
|
pMessage->KeyArgLenMsb = MSBOF(pCanonical->KeyArgLen);
|
||
|
pMessage->KeyArgLenLsb = LSBOF(pCanonical->KeyArgLen);
|
||
|
|
||
|
CopyMemory(pBuffer, pCanonical->KeyArg, pCanonical->KeyArgLen);
|
||
|
|
||
|
return(PCT_ERR_OK);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
SP_STATUS
|
||
|
Ssl2UnpackClientMasterKey(
|
||
|
PSPBuffer pInput,
|
||
|
PSsl2_Client_Master_Key * ppClient)
|
||
|
{
|
||
|
PSsl2_Client_Master_Key pCanonical;
|
||
|
PSSL2_CLIENT_MASTER_KEY pMessage;
|
||
|
PUCHAR pBuffer;
|
||
|
DWORD ReportedSize;
|
||
|
DWORD EncryptedKeyLen;
|
||
|
|
||
|
pMessage = pInput->pvBuffer;
|
||
|
|
||
|
if(pInput->cbData < 2)
|
||
|
{
|
||
|
pInput->cbData = 2;
|
||
|
return PCT_INT_INCOMPLETE_MSG;
|
||
|
}
|
||
|
ReportedSize = SIZEOF(pMessage);
|
||
|
|
||
|
if ((ReportedSize+2) > pInput->cbData)
|
||
|
{
|
||
|
pInput->cbData = ReportedSize+2;
|
||
|
return PCT_INT_INCOMPLETE_MSG;
|
||
|
}
|
||
|
|
||
|
if(ReportedSize < SSL_OFFSET_OF(PSSL2_CLIENT_MASTER_KEY, VariantData))
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
*ppClient = NULL;
|
||
|
|
||
|
if ((pMessage->MessageId != SSL2_MT_CLIENT_MASTER_KEY))
|
||
|
{
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
EncryptedKeyLen = COMBINEBYTES( pMessage->EncryptedKeyLenMsb,
|
||
|
pMessage->EncryptedKeyLenLsb );
|
||
|
|
||
|
pCanonical = (PSsl2_Client_Master_Key)SPExternalAlloc(
|
||
|
sizeof(Ssl2_Client_Master_Key) +
|
||
|
EncryptedKeyLen);
|
||
|
|
||
|
if (!pCanonical)
|
||
|
{
|
||
|
return SP_LOG_RESULT( PCT_INT_INTERNAL_ERROR );
|
||
|
}
|
||
|
|
||
|
pCanonical->CipherKind = Ssl2MapCipherFromExternal( &pMessage->CipherKind );
|
||
|
pCanonical->ClearKeyLen = COMBINEBYTES( pMessage->ClearKeyLenMsb,
|
||
|
pMessage->ClearKeyLenLsb );
|
||
|
|
||
|
pCanonical->EncryptedKeyLen = EncryptedKeyLen;
|
||
|
|
||
|
pCanonical->KeyArgLen = COMBINEBYTES( pMessage->KeyArgLenMsb,
|
||
|
pMessage->KeyArgLenLsb );
|
||
|
|
||
|
|
||
|
//
|
||
|
// Validate
|
||
|
//
|
||
|
if ((pCanonical->ClearKeyLen > SSL2_MASTER_KEY_SIZE) ||
|
||
|
(pCanonical->KeyArgLen > SSL2_MAX_KEY_ARGS))
|
||
|
{
|
||
|
SPExternalFree(pCanonical);
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
|
||
|
if ((SSL_OFFSET_OF(PSSL2_CLIENT_MASTER_KEY, VariantData) -
|
||
|
sizeof(SSL2_MESSAGE_HEADER) +
|
||
|
pCanonical->ClearKeyLen +
|
||
|
pCanonical->EncryptedKeyLen +
|
||
|
pCanonical->KeyArgLen ) !=
|
||
|
ReportedSize)
|
||
|
{
|
||
|
SPExternalFree(pCanonical);
|
||
|
return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
|
||
|
}
|
||
|
|
||
|
pBuffer = pMessage->VariantData;
|
||
|
|
||
|
CopyMemory(pCanonical->ClearKey, pBuffer, pCanonical->ClearKeyLen );
|
||
|
|
||
|
pBuffer += pCanonical->ClearKeyLen;
|
||
|
|
||
|
pCanonical->pbEncryptedKey = (PBYTE)(pCanonical + 1);
|
||
|
CopyMemory(pCanonical->pbEncryptedKey, pBuffer, pCanonical->EncryptedKeyLen );
|
||
|
|
||
|
pBuffer += pCanonical->EncryptedKeyLen;
|
||
|
|
||
|
CopyMemory( pCanonical->KeyArg, pBuffer, pCanonical->KeyArgLen );
|
||
|
|
||
|
*ppClient = pCanonical;
|
||
|
|
||
|
return( PCT_ERR_OK );
|
||
|
}
|
||
|
|