1288 lines
35 KiB
C
1288 lines
35 KiB
C
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: pct1pckl.c
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <spbase.h>
|
|
#include <pct1msg.h>
|
|
#include <pct1prot.h>
|
|
|
|
#define PCT_OFFSET_OF(t, v) ((DWORD)(ULONG_PTR)&(((t)NULL)->v))
|
|
|
|
#define SIZEOF(pMessage) (Pct1RecordSize((PPCT1_MESSAGE_HEADER) pMessage ) )
|
|
|
|
DWORD MapCipherToExternal(CipherSpec Internal, ExtCipherSpec UNALIGNED *External)
|
|
{
|
|
*External = htonl(Internal);
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD MapHashToExternal(HashSpec Internal, ExtHashSpec UNALIGNED *External)
|
|
{
|
|
*External = htons((ExtHashSpec)Internal);
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD MapCertToExternal(CertSpec Internal, ExtCertSpec UNALIGNED *External)
|
|
{
|
|
*External = htons((ExtCertSpec)Internal);
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD MapExchToExternal(ExchSpec Internal, ExtExchSpec UNALIGNED *External)
|
|
{
|
|
*External = htons((ExtExchSpec)Internal);
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD MapSigToExternal(SigSpec Internal, ExtSigSpec UNALIGNED *External)
|
|
{
|
|
*External = htons((ExtSigSpec)Internal);
|
|
return TRUE;
|
|
}
|
|
|
|
CipherSpec MapCipherFromExternal(ExtCipherSpec External)
|
|
{
|
|
return (CipherSpec)ntohl(External);
|
|
}
|
|
|
|
HashSpec MapHashFromExternal(ExtHashSpec External)
|
|
{
|
|
return (HashSpec)ntohs(External);
|
|
}
|
|
|
|
CertSpec MapCertFromExternal(ExtCertSpec External)
|
|
{
|
|
return (CertSpec)ntohs(External);
|
|
}
|
|
|
|
ExchSpec MapExchFromExternal(ExtExchSpec External)
|
|
{
|
|
return (ExchSpec)ntohs(External);
|
|
}
|
|
|
|
SigSpec MapSigFromExternal(ExtSigSpec External)
|
|
{
|
|
return (SigSpec)ntohs(External);
|
|
}
|
|
|
|
|
|
DWORD
|
|
Pct1RecordSize(
|
|
PPCT1_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);
|
|
}
|
|
|
|
|
|
SP_STATUS
|
|
Pct1PackClientHello(
|
|
PPct1_Client_Hello pCanonical,
|
|
PSPBuffer pCommOutput)
|
|
{
|
|
DWORD cbMessage;
|
|
PPCT1_CLIENT_HELLO pMessage;
|
|
DWORD Size;
|
|
PUCHAR pBuffer;
|
|
DWORD i, iBuff;
|
|
|
|
SP_BEGIN("Pct1PackClientHello");
|
|
|
|
if(pCanonical == NULL || pCommOutput == NULL)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
|
|
pCommOutput->cbData = 0;
|
|
|
|
if(pCanonical->cbSessionID != PCT_SESSION_ID_SIZE ||
|
|
pCanonical->cbChallenge != PCT_CHALLENGE_SIZE)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
|
|
|
|
pCommOutput->cbData = PCT_OFFSET_OF(PPCT1_CLIENT_HELLO, VariantData) +
|
|
pCanonical->cCipherSpecs * sizeof(ExtCipherSpec) +
|
|
pCanonical->cHashSpecs * sizeof(ExtHashSpec) +
|
|
pCanonical->cCertSpecs * sizeof(ExtCertSpec) +
|
|
pCanonical->cExchSpecs * sizeof(ExtExchSpec) +
|
|
pCanonical->cbKeyArgSize;
|
|
|
|
|
|
cbMessage = pCommOutput->cbData - sizeof(PCT1_MESSAGE_HEADER);
|
|
if (cbMessage > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
|
|
}
|
|
/* are we allocating our own memory? */
|
|
if(pCommOutput->pvBuffer == NULL)
|
|
{
|
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
|
if (NULL == pCommOutput->pvBuffer)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
|
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
|
}
|
|
|
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
|
{
|
|
// Required size returned in pCommOutput->cbData.
|
|
SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
|
|
}
|
|
|
|
pMessage = pCommOutput->pvBuffer;
|
|
|
|
pMessage->MessageId = PCT1_MSG_CLIENT_HELLO;
|
|
|
|
pMessage->VersionMsb = MSBOF(PCT_VERSION_1);
|
|
pMessage->VersionLsb = LSBOF(PCT_VERSION_1);
|
|
|
|
pMessage->OffsetMsb = MSBOF(PCT_CH_OFFSET_V1);
|
|
pMessage->OffsetLsb = LSBOF(PCT_CH_OFFSET_V1);
|
|
|
|
pMessage->KeyArgLenMsb = MSBOF(pCanonical->cbKeyArgSize);
|
|
pMessage->KeyArgLenLsb = LSBOF(pCanonical->cbKeyArgSize);
|
|
|
|
CopyMemory( pMessage->SessionIdData,
|
|
pCanonical->SessionID,
|
|
pCanonical->cbSessionID);
|
|
|
|
CopyMemory( pMessage->ChallengeData,
|
|
pCanonical->Challenge,
|
|
pCanonical->cbChallenge);
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
iBuff = 0;
|
|
for (i = 0; i < pCanonical->cCipherSpecs ; i++ )
|
|
{
|
|
if (MapCipherToExternal(pCanonical->pCipherSpecs[i],
|
|
&((ExtCipherSpec UNALIGNED *) pBuffer)[iBuff]) )
|
|
{
|
|
iBuff++;
|
|
}
|
|
}
|
|
Size = iBuff*sizeof(ExtCipherSpec);
|
|
|
|
pMessage->CipherSpecsLenMsb = MSBOF(Size);
|
|
pMessage->CipherSpecsLenLsb = LSBOF(Size);
|
|
pBuffer += Size;
|
|
|
|
cbMessage -= (pCanonical->cCipherSpecs - iBuff)*sizeof(ExtCipherSpec);
|
|
|
|
|
|
iBuff = 0;
|
|
for (i = 0; i < pCanonical->cHashSpecs ; i++ )
|
|
{
|
|
if (MapHashToExternal(pCanonical->pHashSpecs[i],
|
|
&((ExtHashSpec UNALIGNED *) pBuffer)[iBuff]) )
|
|
{
|
|
iBuff++;
|
|
}
|
|
}
|
|
Size = iBuff*sizeof(ExtHashSpec);
|
|
pBuffer += Size;
|
|
|
|
pMessage->HashSpecsLenMsb = MSBOF(Size);
|
|
pMessage->HashSpecsLenLsb = LSBOF(Size);
|
|
cbMessage -= (pCanonical->cHashSpecs - iBuff)*sizeof(ExtHashSpec);
|
|
|
|
|
|
iBuff = 0;
|
|
for (i = 0; i < pCanonical->cCertSpecs ; i++ )
|
|
{
|
|
if (MapCertToExternal(pCanonical->pCertSpecs[i],
|
|
&((ExtCertSpec UNALIGNED *) pBuffer)[iBuff]))
|
|
{
|
|
iBuff ++;
|
|
}
|
|
}
|
|
Size = iBuff*sizeof(ExtCertSpec);
|
|
pBuffer += Size;
|
|
|
|
pMessage->CertSpecsLenMsb = MSBOF(Size);
|
|
pMessage->CertSpecsLenLsb = LSBOF(Size);
|
|
cbMessage -= (pCanonical->cCertSpecs - iBuff)*sizeof(ExtCertSpec);
|
|
|
|
|
|
iBuff = 0;
|
|
for (i = 0; i < pCanonical->cExchSpecs ; i++ )
|
|
{
|
|
if (MapExchToExternal(pCanonical->pExchSpecs[i],
|
|
&((ExtExchSpec UNALIGNED *) pBuffer)[iBuff]) )
|
|
{
|
|
iBuff++;
|
|
}
|
|
}
|
|
Size = iBuff*sizeof(ExtExchSpec);
|
|
pBuffer += Size;
|
|
|
|
|
|
pMessage->ExchSpecsLenMsb = MSBOF(Size);
|
|
pMessage->ExchSpecsLenLsb = LSBOF(Size);
|
|
cbMessage -= (pCanonical->cExchSpecs - iBuff)*sizeof(ExtExchSpec);
|
|
|
|
if(pCanonical->pKeyArg)
|
|
{
|
|
CopyMemory(pBuffer, pCanonical->pKeyArg, pCanonical->cbKeyArgSize);
|
|
pBuffer += pCanonical->cbKeyArgSize;
|
|
}
|
|
|
|
pCommOutput->cbData = cbMessage + 2;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
|
|
|
SP_RETURN(PCT_ERR_OK);
|
|
}
|
|
|
|
SP_STATUS
|
|
Pct1UnpackClientHello(
|
|
PSPBuffer pInput,
|
|
PPct1_Client_Hello * ppClient)
|
|
{
|
|
|
|
PPCT1_CLIENT_HELLO pMessage;
|
|
|
|
DWORD ReportedSize;
|
|
DWORD CipherSpecsSize, HashSpecsSize, CertSpecsSize;
|
|
DWORD ExchSpecsSize;
|
|
DWORD cCipherSpecs, cHashSpecs, cCertSpecs, cExchSpecs;
|
|
DWORD cOffsetBytes, KeyArgSize;
|
|
PPct1_Client_Hello pCanonical;
|
|
PUCHAR pBuffer;
|
|
DWORD i;
|
|
|
|
SP_BEGIN("Pct1UnpackClientHello");
|
|
|
|
if(pInput == NULL ||
|
|
ppClient == NULL ||
|
|
pInput->pvBuffer == NULL)
|
|
{
|
|
SP_RETURN(PCT_INT_INTERNAL_ERROR);
|
|
}
|
|
|
|
pMessage = pInput->pvBuffer;
|
|
|
|
if(pInput->cbData < 2)
|
|
{
|
|
pInput->cbData = 2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
|
|
if ((ReportedSize+2) > pInput->cbData)
|
|
{
|
|
pInput->cbData = ReportedSize+2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
if(ReportedSize < PCT_OFFSET_OF(PPCT1_CLIENT_HELLO, VariantData))
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
if(ReportedSize > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
if ((pMessage->VersionMsb & 0x80) == 0)
|
|
{
|
|
SP_RETURN (PCT_ERR_SSL_STYLE_MSG);
|
|
}
|
|
|
|
/* We don't recognize hello messages of less version than ourselves,
|
|
* those will be handled by a previous version of the code */
|
|
if ((pMessage->MessageId != PCT1_MSG_CLIENT_HELLO) ||
|
|
((pMessage->VersionMsb << 8 | pMessage->VersionLsb) < PCT_VERSION_1))
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
cOffsetBytes = COMBINEBYTES( pMessage->OffsetMsb,
|
|
pMessage->OffsetLsb );
|
|
|
|
if(cOffsetBytes < PCT_CH_OFFSET_V1)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
*ppClient = NULL;
|
|
|
|
CipherSpecsSize = COMBINEBYTES( pMessage->CipherSpecsLenMsb,
|
|
pMessage->CipherSpecsLenLsb );
|
|
|
|
HashSpecsSize = COMBINEBYTES( pMessage->HashSpecsLenMsb,
|
|
pMessage->HashSpecsLenLsb );
|
|
|
|
CertSpecsSize = COMBINEBYTES( pMessage->CertSpecsLenMsb,
|
|
pMessage->CertSpecsLenLsb );
|
|
|
|
ExchSpecsSize = COMBINEBYTES( pMessage->ExchSpecsLenMsb,
|
|
pMessage->ExchSpecsLenLsb );
|
|
|
|
KeyArgSize = COMBINEBYTES( pMessage->KeyArgLenMsb,
|
|
pMessage->KeyArgLenLsb );
|
|
|
|
/* check that this all fits into the message */
|
|
if (PCT_OFFSET_OF(PPCT1_CLIENT_HELLO, VariantData)
|
|
- sizeof(PCT1_MESSAGE_HEADER) /* don't count the header */
|
|
+ cOffsetBytes - PCT_CH_OFFSET_V1
|
|
+ CipherSpecsSize
|
|
+ HashSpecsSize
|
|
+ CertSpecsSize
|
|
+ ExchSpecsSize
|
|
+ KeyArgSize != ReportedSize)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
cCipherSpecs = CipherSpecsSize / sizeof(ExtCipherSpec);
|
|
cHashSpecs = HashSpecsSize / sizeof(ExtHashSpec);
|
|
cExchSpecs = ExchSpecsSize / sizeof(ExtExchSpec);
|
|
cCertSpecs = CertSpecsSize / sizeof(ExtCertSpec);
|
|
|
|
if(KeyArgSize > SP_MAX_KEY_ARGS)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
|
|
/* Allocate a buffer for the canonical client hello */
|
|
pCanonical = (PPct1_Client_Hello)SPExternalAlloc(
|
|
sizeof(Pct1_Client_Hello) +
|
|
cCipherSpecs * sizeof(CipherSpec) +
|
|
cHashSpecs * sizeof(HashSpec) +
|
|
cCertSpecs * sizeof(CertSpec) +
|
|
cExchSpecs * sizeof(ExchSpec) +
|
|
KeyArgSize);
|
|
|
|
if (!pCanonical)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
|
|
pCanonical->cbKeyArgSize = KeyArgSize;
|
|
|
|
pCanonical->pCipherSpecs = (PCipherSpec) (pCanonical + 1);
|
|
pCanonical->pHashSpecs = (PHashSpec) (pCanonical->pCipherSpecs +
|
|
cCipherSpecs);
|
|
pCanonical->pCertSpecs = (PCertSpec) (pCanonical->pHashSpecs +
|
|
cHashSpecs);
|
|
pCanonical->pExchSpecs = (PExchSpec) (pCanonical->pCertSpecs +
|
|
cCertSpecs);
|
|
|
|
pCanonical->pKeyArg = (PUCHAR)(pCanonical->pExchSpecs + cExchSpecs);
|
|
|
|
CopyMemory( pCanonical->SessionID,
|
|
pMessage->SessionIdData,
|
|
PCT_SESSION_ID_SIZE);
|
|
pCanonical->cbSessionID = PCT_SESSION_ID_SIZE;
|
|
|
|
CopyMemory( pCanonical->Challenge,
|
|
pMessage->ChallengeData,
|
|
PCT_CHALLENGE_SIZE );
|
|
pCanonical->cbChallenge = PCT_CHALLENGE_SIZE;
|
|
|
|
|
|
pBuffer = &pMessage->OffsetLsb + 1 + cOffsetBytes;
|
|
|
|
pCanonical->cCipherSpecs = cCipherSpecs;
|
|
|
|
for (i = 0 ; i < cCipherSpecs ; i++ )
|
|
{
|
|
pCanonical->pCipherSpecs[i] = MapCipherFromExternal(*(ExtCipherSpec UNALIGNED *)
|
|
pBuffer);
|
|
|
|
pBuffer += sizeof(ExtCipherSpec);
|
|
}
|
|
|
|
pCanonical->cHashSpecs = cHashSpecs;
|
|
|
|
for (i = 0 ; i < cHashSpecs ; i++ )
|
|
{
|
|
pCanonical->pHashSpecs[i] = MapHashFromExternal(*(ExtHashSpec UNALIGNED *)
|
|
pBuffer);
|
|
|
|
pBuffer += sizeof(ExtHashSpec);
|
|
}
|
|
|
|
pCanonical->cCertSpecs = cCertSpecs;
|
|
|
|
for (i = 0 ; i < cCertSpecs ; i++ )
|
|
{
|
|
pCanonical->pCertSpecs[i] = MapCertFromExternal(*(ExtCertSpec UNALIGNED *)
|
|
pBuffer);
|
|
|
|
pBuffer += sizeof(ExtCertSpec);
|
|
}
|
|
|
|
pCanonical->cExchSpecs = cExchSpecs;
|
|
|
|
for (i = 0 ; i < cExchSpecs ; i++ )
|
|
{
|
|
pCanonical->pExchSpecs[i] = MapExchFromExternal(*(ExtExchSpec UNALIGNED *)
|
|
pBuffer);
|
|
|
|
pBuffer += sizeof(ExtExchSpec);
|
|
}
|
|
|
|
|
|
CopyMemory(pCanonical->pKeyArg, pBuffer, KeyArgSize);
|
|
|
|
*ppClient = pCanonical;
|
|
pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
|
|
|
|
SP_RETURN(PCT_ERR_OK);
|
|
}
|
|
|
|
SP_STATUS
|
|
Pct1PackServerHello(
|
|
PPct1_Server_Hello pCanonical,
|
|
PSPBuffer pCommOutput)
|
|
{
|
|
DWORD cbMessage;
|
|
PPCT1_SERVER_HELLO pMessage;
|
|
DWORD Size;
|
|
PUCHAR pBuffer;
|
|
DWORD i, iBuff;
|
|
|
|
|
|
SP_BEGIN("Pct1PackServerHello");
|
|
|
|
if(pCanonical == NULL || pCommOutput == NULL)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
|
|
pCommOutput->cbData = 0;
|
|
if(pCanonical->cbConnectionID != PCT_SESSION_ID_SIZE)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
|
|
cbMessage = pCanonical->CertificateLen +
|
|
pCanonical->cCertSpecs * sizeof(ExtCertSpec) +
|
|
pCanonical->cSigSpecs * sizeof(ExtSigSpec) +
|
|
pCanonical->ResponseLen +
|
|
PCT_OFFSET_OF(PPCT1_SERVER_HELLO, VariantData) -
|
|
sizeof(PCT1_MESSAGE_HEADER);
|
|
|
|
if (cbMessage > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
|
|
}
|
|
|
|
pCommOutput->cbData = cbMessage + 2;
|
|
|
|
/* are we allocating our own memory? */
|
|
if(pCommOutput->pvBuffer == NULL)
|
|
{
|
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
|
if (NULL == pCommOutput->pvBuffer)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
|
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
|
}
|
|
|
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
|
{
|
|
// Required size returned in pCommOutput->cbData.
|
|
SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
|
|
}
|
|
|
|
pMessage = pCommOutput->pvBuffer;
|
|
|
|
|
|
pMessage->MessageId = PCT1_MSG_SERVER_HELLO;
|
|
pMessage->ServerVersionMsb = MSBOF(PCT_VERSION_1);
|
|
pMessage->ServerVersionLsb = LSBOF(PCT_VERSION_1);
|
|
pMessage->RestartSessionOK = (UCHAR) pCanonical->RestartOk;
|
|
pMessage->ClientAuthReq = (UCHAR)pCanonical->ClientAuthReq;
|
|
|
|
MapCipherToExternal(pCanonical->SrvCipherSpec, &pMessage->CipherSpecData);
|
|
MapHashToExternal(pCanonical->SrvHashSpec, &pMessage->HashSpecData);
|
|
MapCertToExternal(pCanonical->SrvCertSpec, &pMessage->CertSpecData);
|
|
MapExchToExternal(pCanonical->SrvExchSpec, &pMessage->ExchSpecData);
|
|
|
|
CopyMemory(pMessage->ConnectionIdData, pCanonical->ConnectionID,
|
|
pCanonical->cbConnectionID);
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
|
|
/* Pack certificate if present */
|
|
|
|
|
|
pMessage->CertificateLenMsb = MSBOF(pCanonical->CertificateLen);
|
|
pMessage->CertificateLenLsb = LSBOF(pCanonical->CertificateLen);
|
|
|
|
if (pCanonical->CertificateLen)
|
|
{
|
|
CopyMemory( pBuffer,
|
|
pCanonical->pCertificate,
|
|
pCanonical->CertificateLen);
|
|
|
|
pBuffer += pCanonical->CertificateLen ;
|
|
}
|
|
|
|
iBuff = 0;
|
|
for (i = 0; i < pCanonical->cCertSpecs ; i++ )
|
|
{
|
|
if (MapCertToExternal(pCanonical->pClientCertSpecs[i],
|
|
&((ExtCertSpec UNALIGNED *) pBuffer)[iBuff]))
|
|
{
|
|
iBuff ++;
|
|
}
|
|
}
|
|
Size = iBuff*sizeof(ExtCertSpec);
|
|
pBuffer += Size;
|
|
|
|
pMessage->CertSpecsLenMsb = MSBOF(Size);
|
|
pMessage->CertSpecsLenLsb = LSBOF(Size);
|
|
cbMessage -= (pCanonical->cCertSpecs - iBuff)*sizeof(ExtCertSpec);
|
|
|
|
iBuff = 0;
|
|
for (i = 0; i < pCanonical->cSigSpecs ; i++ )
|
|
{
|
|
if (MapSigToExternal(pCanonical->pClientSigSpecs[i],
|
|
&((ExtSigSpec UNALIGNED *) pBuffer)[iBuff]) )
|
|
{
|
|
iBuff++;
|
|
}
|
|
}
|
|
Size = iBuff*sizeof(ExtSigSpec);
|
|
pBuffer += Size;
|
|
|
|
pMessage->ClientSigSpecsLenMsb = MSBOF(Size);
|
|
pMessage->ClientSigSpecsLenLsb = LSBOF(Size);
|
|
cbMessage -= (pCanonical->cSigSpecs - iBuff)*sizeof(ExtSigSpec);
|
|
|
|
pMessage->ResponseLenMsb = MSBOF(pCanonical->ResponseLen);
|
|
pMessage->ResponseLenLsb = LSBOF(pCanonical->ResponseLen);
|
|
|
|
CopyMemory( pBuffer,
|
|
pCanonical->Response,
|
|
pCanonical->ResponseLen);
|
|
|
|
pBuffer += pCanonical->ResponseLen;
|
|
|
|
pCommOutput->cbData = cbMessage + 2;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
|
|
|
|
|
SP_RETURN(PCT_ERR_OK);
|
|
|
|
}
|
|
|
|
SP_STATUS
|
|
Pct1UnpackServerHello(
|
|
PSPBuffer pInput,
|
|
PPct1_Server_Hello * ppServer)
|
|
{
|
|
PPct1_Server_Hello pCanonical;
|
|
PPCT1_SERVER_HELLO pMessage;
|
|
PUCHAR pBuffer;
|
|
DWORD cbCertificate, cbResponse;
|
|
DWORD cCertSpecs, cSigSpecs;
|
|
DWORD i;
|
|
DWORD ReportedSize;
|
|
|
|
SP_BEGIN("Pct1UnpackServerHello");
|
|
|
|
if(pInput == NULL ||
|
|
ppServer == NULL ||
|
|
pInput->pvBuffer == NULL)
|
|
{
|
|
SP_RETURN(PCT_INT_INTERNAL_ERROR);
|
|
}
|
|
|
|
pMessage = pInput->pvBuffer;
|
|
|
|
if(pInput->cbData < 2)
|
|
{
|
|
pInput->cbData = 2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
if(ReportedSize > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
if ((ReportedSize+2) > pInput->cbData)
|
|
{
|
|
pInput->cbData = ReportedSize+2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
if(ReportedSize < PCT_OFFSET_OF(PPCT1_SERVER_HELLO, VariantData) )
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
/* Verify Header: */
|
|
|
|
/* we don't handle server hello messages of latter version than ourselves,
|
|
* those will be handled by latter verisions of the protocol */
|
|
if ((pMessage->MessageId != PCT1_MSG_SERVER_HELLO) ||
|
|
((pMessage->ServerVersionMsb << 8 | pMessage->ServerVersionLsb) != PCT_VERSION_1))
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
*ppServer = NULL;
|
|
|
|
cbCertificate = COMBINEBYTES(pMessage->CertificateLenMsb,
|
|
pMessage->CertificateLenLsb);
|
|
|
|
cCertSpecs = COMBINEBYTES(pMessage->CertSpecsLenMsb,
|
|
pMessage->CertSpecsLenLsb);
|
|
|
|
cCertSpecs /= sizeof(ExtCertSpec);
|
|
|
|
|
|
cSigSpecs = COMBINEBYTES(pMessage->ClientSigSpecsLenMsb,
|
|
pMessage->ClientSigSpecsLenLsb);
|
|
|
|
cSigSpecs /= sizeof(ExtSigSpec);
|
|
|
|
cbResponse = COMBINEBYTES(pMessage->ResponseLenMsb,
|
|
pMessage->ResponseLenLsb);
|
|
|
|
if(cbResponse > PCT1_RESPONSE_SIZE)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
/* check that this all fits into the message */
|
|
if (PCT_OFFSET_OF(PPCT1_SERVER_HELLO, VariantData)
|
|
- sizeof(PCT1_MESSAGE_HEADER) /* don't count the header */
|
|
+ cbCertificate
|
|
+ cCertSpecs*sizeof(ExtCertSpec)
|
|
+ cSigSpecs*sizeof(ExtSigSpec)
|
|
+ cbResponse != ReportedSize)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
pCanonical = (PPct1_Server_Hello)SPExternalAlloc(
|
|
sizeof(Pct1_Server_Hello) +
|
|
cCertSpecs * sizeof(CertSpec) +
|
|
cSigSpecs * sizeof(SigSpec) +
|
|
cbCertificate);
|
|
|
|
if (!pCanonical)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
|
|
|
|
/* Set up pointers to be in this memory allocation. */
|
|
|
|
|
|
pCanonical->pClientCertSpecs = (PCertSpec) (pCanonical + 1);
|
|
pCanonical->pClientSigSpecs = (PSigSpec)(pCanonical->pClientCertSpecs +
|
|
cCertSpecs);
|
|
|
|
pCanonical->pCertificate = (PUCHAR) (pCanonical->pClientSigSpecs +
|
|
cSigSpecs);
|
|
|
|
/* Expand out: */
|
|
|
|
pCanonical->RestartOk = (DWORD) pMessage->RestartSessionOK;
|
|
pCanonical->ClientAuthReq = (DWORD)pMessage->ClientAuthReq;
|
|
pCanonical->SrvCertSpec = MapCertFromExternal(pMessage->CertSpecData);
|
|
pCanonical->SrvCipherSpec =MapCipherFromExternal(pMessage->CipherSpecData);
|
|
pCanonical->SrvHashSpec = MapHashFromExternal(pMessage->HashSpecData);
|
|
pCanonical->SrvExchSpec = MapExchFromExternal(pMessage->ExchSpecData);
|
|
pCanonical->CertificateLen = cbCertificate;
|
|
pCanonical->ResponseLen = cbResponse;
|
|
pCanonical->cCertSpecs = cCertSpecs;
|
|
pCanonical->cSigSpecs = cSigSpecs;
|
|
|
|
CopyMemory(pCanonical->ConnectionID,
|
|
pMessage->ConnectionIdData,
|
|
PCT_SESSION_ID_SIZE);
|
|
|
|
pCanonical->cbConnectionID= PCT_SESSION_ID_SIZE;
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
CopyMemory(pCanonical->pCertificate, pBuffer, cbCertificate);
|
|
pBuffer += cbCertificate;
|
|
|
|
for (i = 0 ; i < cCertSpecs ; i++ )
|
|
{
|
|
pCanonical->pClientCertSpecs[i] = MapCertFromExternal(
|
|
*(ExtCertSpec UNALIGNED *)pBuffer);
|
|
pBuffer += sizeof(ExtCertSpec);
|
|
}
|
|
|
|
for (i = 0 ; i < cSigSpecs ; i++ )
|
|
{
|
|
pCanonical->pClientSigSpecs[i] = MapSigFromExternal(
|
|
*(ExtSigSpec UNALIGNED *)pBuffer);
|
|
pBuffer += sizeof(ExtSigSpec);
|
|
}
|
|
|
|
CopyMemory(pCanonical->Response, pBuffer, cbResponse);
|
|
|
|
|
|
*ppServer = pCanonical;
|
|
pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
|
|
|
|
SP_RETURN(PCT_ERR_OK);
|
|
|
|
}
|
|
|
|
SP_STATUS
|
|
Pct1PackClientMasterKey(
|
|
PPct1_Client_Master_Key pCanonical,
|
|
PSPBuffer pCommOutput)
|
|
{
|
|
DWORD cbMessage;
|
|
PPCT1_CLIENT_MASTER_KEY pMessage;
|
|
PUCHAR pBuffer;
|
|
|
|
SP_BEGIN("Pct1PackClientMasterKey");
|
|
|
|
if(pCanonical == NULL || pCommOutput == NULL)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
|
|
pCommOutput->cbData = 0;
|
|
|
|
cbMessage = pCanonical->ClearKeyLen +
|
|
pCanonical->EncryptedKeyLen +
|
|
pCanonical->KeyArgLen +
|
|
pCanonical->VerifyPreludeLen +
|
|
pCanonical->ClientCertLen +
|
|
pCanonical->ResponseLen +
|
|
PCT_OFFSET_OF(PPCT1_CLIENT_MASTER_KEY, VariantData) -
|
|
sizeof(PCT1_MESSAGE_HEADER);
|
|
|
|
if (cbMessage > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
|
|
}
|
|
|
|
pCommOutput->cbData = cbMessage + 2;
|
|
|
|
/* are we allocating our own memory? */
|
|
if(pCommOutput->pvBuffer == NULL)
|
|
{
|
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
|
if (NULL == pCommOutput->pvBuffer)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
|
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
|
}
|
|
|
|
|
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
|
{
|
|
// Required size returned in pCommOutput->cbData.
|
|
SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
|
|
}
|
|
|
|
pMessage = pCommOutput->pvBuffer;
|
|
|
|
|
|
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
|
|
|
pMessage->MessageId = PCT1_MSG_CLIENT_MASTER_KEY;
|
|
|
|
pMessage->ClearKeyLenMsb = MSBOF(pCanonical->ClearKeyLen);
|
|
pMessage->ClearKeyLenLsb = LSBOF(pCanonical->ClearKeyLen);
|
|
|
|
MapSigToExternal(pCanonical->ClientSigSpec, &pMessage->ClientSigSpecData);
|
|
MapCertToExternal(pCanonical->ClientCertSpec, &pMessage->ClientCertSpecData);
|
|
|
|
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);
|
|
pBuffer += pCanonical->KeyArgLen;
|
|
|
|
pMessage->VerifyPreludeLenMsb = MSBOF(pCanonical->VerifyPreludeLen);
|
|
pMessage->VerifyPreludeLenLsb = LSBOF(pCanonical->VerifyPreludeLen);
|
|
|
|
CopyMemory(pBuffer, pCanonical->VerifyPrelude,
|
|
pCanonical->VerifyPreludeLen);
|
|
pBuffer += pCanonical->VerifyPreludeLen;
|
|
|
|
pMessage->ClientCertLenMsb = MSBOF(pCanonical->ClientCertLen);
|
|
pMessage->ClientCertLenLsb = LSBOF(pCanonical->ClientCertLen);
|
|
|
|
CopyMemory(pBuffer, pCanonical->pClientCert, pCanonical->ClientCertLen);
|
|
pBuffer += pCanonical->ClientCertLen;
|
|
|
|
pMessage->ResponseLenMsb = MSBOF(pCanonical->ResponseLen);
|
|
pMessage->ResponseLenLsb = LSBOF(pCanonical->ResponseLen);
|
|
|
|
CopyMemory(pBuffer, pCanonical->pbResponse, pCanonical->ResponseLen);
|
|
|
|
|
|
SP_RETURN(PCT_ERR_OK);
|
|
|
|
}
|
|
|
|
SP_STATUS
|
|
Pct1UnpackClientMasterKey(
|
|
PSPBuffer pInput,
|
|
PPct1_Client_Master_Key * ppClient)
|
|
{
|
|
PPct1_Client_Master_Key pCanonical;
|
|
|
|
PUCHAR pBuffer;
|
|
DWORD ReportedSize;
|
|
PPCT1_CLIENT_MASTER_KEY pMessage;
|
|
DWORD cbClearKey, cbEncryptedKey, cbKeyArg, cbVerifyPrelude, cbClientCert, cbResponse;
|
|
|
|
SP_BEGIN("Pct1UnpackClientMasterKey");
|
|
|
|
if(pInput == NULL ||
|
|
ppClient == NULL ||
|
|
pInput->pvBuffer == NULL)
|
|
{
|
|
SP_RETURN(PCT_INT_INTERNAL_ERROR);
|
|
}
|
|
|
|
pMessage = pInput->pvBuffer;
|
|
|
|
if(pInput->cbData < 2)
|
|
{
|
|
pInput->cbData = 2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
if(ReportedSize > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
if ((ReportedSize+2) > pInput->cbData)
|
|
{
|
|
pInput->cbData = ReportedSize+2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
if(ReportedSize < PCT_OFFSET_OF(PPCT1_CLIENT_MASTER_KEY, VariantData))
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
/* Verify Header: */
|
|
|
|
|
|
if (pMessage->MessageId != PCT1_MSG_CLIENT_MASTER_KEY )
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
cbClearKey = COMBINEBYTES( pMessage->ClearKeyLenMsb,
|
|
pMessage->ClearKeyLenLsb );
|
|
|
|
cbEncryptedKey = COMBINEBYTES( pMessage->EncryptedKeyLenMsb,
|
|
pMessage->EncryptedKeyLenLsb );
|
|
|
|
cbKeyArg = COMBINEBYTES( pMessage->KeyArgLenMsb,
|
|
pMessage->KeyArgLenLsb );
|
|
|
|
cbVerifyPrelude = COMBINEBYTES( pMessage->VerifyPreludeLenMsb,
|
|
pMessage->VerifyPreludeLenLsb );
|
|
|
|
cbClientCert = COMBINEBYTES( pMessage->ClientCertLenMsb,
|
|
pMessage->ClientCertLenLsb );
|
|
|
|
cbResponse = COMBINEBYTES( pMessage->ResponseLenMsb,
|
|
pMessage->ResponseLenLsb );
|
|
|
|
/* defensive checks..... */
|
|
|
|
if ((cbClearKey > SP_MAX_MASTER_KEY) ||
|
|
(cbKeyArg > PCT1_MAX_KEY_ARGS) ||
|
|
(cbVerifyPrelude > RESPONSE_SIZE))
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
|
|
if ((PCT_OFFSET_OF(PPCT1_CLIENT_MASTER_KEY, VariantData) -
|
|
sizeof(PCT1_MESSAGE_HEADER) +
|
|
cbClearKey +
|
|
cbEncryptedKey +
|
|
cbKeyArg +
|
|
cbVerifyPrelude +
|
|
cbClientCert +
|
|
cbResponse) !=
|
|
ReportedSize)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
|
|
*ppClient = NULL;
|
|
|
|
|
|
pCanonical = (PPct1_Client_Master_Key)SPExternalAlloc(
|
|
sizeof(Pct1_Client_Master_Key) +
|
|
cbClientCert +
|
|
cbEncryptedKey +
|
|
cbResponse);
|
|
|
|
if (!pCanonical)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
|
|
}
|
|
|
|
pCanonical->ClearKeyLen = cbClearKey;
|
|
|
|
pCanonical->EncryptedKeyLen = cbEncryptedKey;
|
|
|
|
pCanonical->KeyArgLen = cbKeyArg;
|
|
|
|
pCanonical->VerifyPreludeLen = cbVerifyPrelude;
|
|
pCanonical->ClientCertLen = cbClientCert;
|
|
|
|
pCanonical->ResponseLen = cbResponse;
|
|
/* defensive checks..... */
|
|
|
|
|
|
pCanonical->ClientCertSpec = MapCertFromExternal(pMessage->ClientCertSpecData);
|
|
|
|
pCanonical->pClientCert = (PUCHAR)(pCanonical+1);
|
|
|
|
pCanonical->ClientSigSpec = MapSigFromExternal(pMessage->ClientSigSpecData);
|
|
/* ok, we're pretty sure we aren't going to fault. */
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
CopyMemory(pCanonical->ClearKey, pBuffer, pCanonical->ClearKeyLen );
|
|
|
|
pBuffer += pCanonical->ClearKeyLen;
|
|
|
|
pCanonical->pbEncryptedKey = pCanonical->pClientCert + cbClientCert;
|
|
CopyMemory(pCanonical->pbEncryptedKey, pBuffer, pCanonical->EncryptedKeyLen);
|
|
|
|
pBuffer += pCanonical->EncryptedKeyLen;
|
|
|
|
CopyMemory( pCanonical->KeyArg, pBuffer, pCanonical->KeyArgLen );
|
|
|
|
pBuffer += pCanonical->KeyArgLen;
|
|
|
|
CopyMemory( pCanonical->VerifyPrelude, pBuffer,
|
|
pCanonical->VerifyPreludeLen );
|
|
|
|
pBuffer += pCanonical->VerifyPreludeLen;
|
|
|
|
CopyMemory( pCanonical->pClientCert, pBuffer, pCanonical->ClientCertLen );
|
|
|
|
pBuffer += pCanonical->ClientCertLen;
|
|
|
|
pCanonical->pbResponse = pCanonical->pbEncryptedKey + cbEncryptedKey;
|
|
CopyMemory( pCanonical->pbResponse, pBuffer, pCanonical->ResponseLen );
|
|
|
|
*ppClient = pCanonical;
|
|
pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
|
|
SP_RETURN( PCT_ERR_OK );
|
|
}
|
|
|
|
|
|
SP_STATUS
|
|
Pct1PackServerVerify(
|
|
PPct1_Server_Verify pCanonical,
|
|
PSPBuffer pCommOutput)
|
|
{
|
|
DWORD cbMessage;
|
|
PPCT1_SERVER_VERIFY pMessage;
|
|
PUCHAR pBuffer;
|
|
|
|
|
|
SP_BEGIN("Pct1PackServerVerify");
|
|
|
|
if(pCanonical == NULL || pCommOutput == NULL)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
|
|
pCommOutput->cbData = 0;
|
|
|
|
cbMessage = pCanonical->ResponseLen +
|
|
PCT_OFFSET_OF(PPCT1_SERVER_VERIFY, VariantData) -
|
|
sizeof(PCT1_MESSAGE_HEADER);
|
|
|
|
if (cbMessage > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(PCT_INT_DATA_OVERFLOW);
|
|
}
|
|
|
|
pCommOutput->cbData = cbMessage + 2;
|
|
|
|
/* are we allocating our own memory? */
|
|
if(pCommOutput->pvBuffer == NULL)
|
|
{
|
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
|
if (NULL == pCommOutput->pvBuffer)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
|
}
|
|
|
|
|
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
|
{
|
|
// Required size returned in pCommOutput->cbData.
|
|
SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
|
|
}
|
|
|
|
pMessage = pCommOutput->pvBuffer;
|
|
|
|
pMessage->MessageId = PCT1_MSG_SERVER_VERIFY;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
|
|
|
CopyMemory(pMessage->SessionIdData, pCanonical->SessionIdData,
|
|
PCT_SESSION_ID_SIZE);
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
|
|
/* Pack certificate if present */
|
|
|
|
|
|
pMessage->ResponseLenMsb = MSBOF(pCanonical->ResponseLen);
|
|
pMessage->ResponseLenLsb = LSBOF(pCanonical->ResponseLen);
|
|
|
|
if (pCanonical->ResponseLen)
|
|
{
|
|
CopyMemory( pBuffer,
|
|
pCanonical->Response,
|
|
pCanonical->ResponseLen);
|
|
}
|
|
|
|
SP_RETURN( PCT_ERR_OK );
|
|
|
|
}
|
|
|
|
SP_STATUS
|
|
Pct1UnpackServerVerify(
|
|
PSPBuffer pInput,
|
|
PPct1_Server_Verify * ppServer)
|
|
{
|
|
PPct1_Server_Verify pCanonical;
|
|
PPCT1_SERVER_VERIFY pMessage;
|
|
PUCHAR pBuffer;
|
|
DWORD cbResponse;
|
|
DWORD ReportedSize;
|
|
|
|
SP_BEGIN("Pct1UnpackServerVerify");
|
|
|
|
if(pInput == NULL ||
|
|
ppServer == NULL ||
|
|
pInput->pvBuffer == NULL)
|
|
{
|
|
SP_RETURN(PCT_INT_INTERNAL_ERROR);
|
|
}
|
|
|
|
pMessage = pInput->pvBuffer;
|
|
|
|
if(pInput->cbData < 2)
|
|
{
|
|
pInput->cbData = 2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
if(ReportedSize > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
if ((ReportedSize+2) > pInput->cbData)
|
|
{
|
|
pInput->cbData = ReportedSize+2;
|
|
SP_RETURN(PCT_INT_INCOMPLETE_MSG);
|
|
}
|
|
|
|
if(ReportedSize < PCT_OFFSET_OF(PPCT1_SERVER_VERIFY, VariantData))
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
/* Verify Header: */
|
|
|
|
|
|
if (pMessage->MessageId != PCT1_MSG_SERVER_VERIFY )
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
|
|
*ppServer = NULL;
|
|
|
|
/* Verify Header: */
|
|
|
|
|
|
cbResponse = COMBINEBYTES(pMessage->ResponseLenMsb,
|
|
pMessage->ResponseLenLsb);
|
|
|
|
if (cbResponse > PCT_SESSION_ID_SIZE)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
if ((PCT_OFFSET_OF(PPCT1_SERVER_VERIFY, VariantData) -
|
|
sizeof(PCT1_MESSAGE_HEADER) +
|
|
cbResponse ) !=
|
|
ReportedSize)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
|
|
}
|
|
|
|
pCanonical = (PPct1_Server_Verify)SPExternalAlloc( sizeof(Pct1_Server_Verify));
|
|
|
|
if (!pCanonical)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
|
|
|
|
/* Expand out: */
|
|
|
|
|
|
pCanonical->ResponseLen = cbResponse;
|
|
|
|
CopyMemory((PUCHAR)pCanonical->SessionIdData, pMessage->SessionIdData,
|
|
PCT_SESSION_ID_SIZE);
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
CopyMemory(pCanonical->Response, pBuffer, cbResponse);
|
|
|
|
*ppServer = pCanonical;
|
|
pInput->cbData = ReportedSize + sizeof(PCT1_MESSAGE_HEADER);
|
|
SP_RETURN(PCT_ERR_OK);
|
|
}
|
|
|
|
|
|
SP_STATUS
|
|
Pct1PackError(
|
|
PPct1_Error pCanonical,
|
|
PSPBuffer pCommOutput)
|
|
{
|
|
DWORD cbMessage;
|
|
PPCT1_ERROR pMessage;
|
|
|
|
|
|
SP_BEGIN("Pct1PackError");
|
|
|
|
if(pCanonical == NULL || pCommOutput == NULL)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR));
|
|
}
|
|
pCommOutput->cbData = 0;
|
|
|
|
cbMessage = pCanonical->ErrInfoLen +
|
|
PCT_OFFSET_OF(PPCT1_ERROR, VariantData) -
|
|
sizeof(PCT1_MESSAGE_HEADER);
|
|
|
|
if (cbMessage > PCT_MAX_SHAKE_LEN)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(PCT_INT_DATA_OVERFLOW));
|
|
}
|
|
|
|
pCommOutput->cbData = cbMessage+2;
|
|
|
|
/* are we allocating our own memory? */
|
|
if(pCommOutput->pvBuffer == NULL)
|
|
{
|
|
pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
|
|
if (NULL == pCommOutput->pvBuffer)
|
|
{
|
|
SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
|
|
}
|
|
pCommOutput->cbBuffer = pCommOutput->cbData;
|
|
}
|
|
|
|
|
|
if(pCommOutput->cbData > pCommOutput->cbBuffer)
|
|
{
|
|
// Required size returned in pCommOutput->cbData.
|
|
SP_RETURN(PCT_INT_BUFF_TOO_SMALL);
|
|
}
|
|
|
|
pMessage = pCommOutput->pvBuffer;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(cbMessage) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(cbMessage);
|
|
|
|
pMessage->MessageId = PCT1_MSG_ERROR;
|
|
|
|
pMessage->ErrorMsb = MSBOF(pCanonical->Error);
|
|
pMessage->ErrorLsb = LSBOF(pCanonical->Error);
|
|
|
|
pMessage->ErrorInfoMsb = MSBOF(pCanonical->ErrInfoLen);
|
|
pMessage->ErrorInfoLsb = LSBOF(pCanonical->ErrInfoLen);
|
|
|
|
if(pCanonical->ErrInfoLen) {
|
|
CopyMemory(pMessage->VariantData, pCanonical->ErrInfo, pCanonical->ErrInfoLen);
|
|
}
|
|
|
|
SP_RETURN( PCT_ERR_OK );
|
|
}
|