mirror of https://github.com/lianthony/NT4.0
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.
785 lines
20 KiB
785 lines
20 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: pickle.c
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 8-02-95 RichardW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "sslsspi.h"
|
|
|
|
typedef struct _CipherMapping {
|
|
DWORD FastForm;
|
|
Ssl_Cipher_Tuple ThreeByteForm;
|
|
} CipherMapping, * PCipherMapping;
|
|
|
|
|
|
CipherSpec * SslAvailableCiphers;
|
|
DWORD SslNumberAvailableCiphers;
|
|
PCipherMapping pCKMappings;
|
|
DWORD cMappings;
|
|
Ssl_Cipher_Tuple MappingInitVector[] = {
|
|
SSL_CK_RC4_128_WITH_MD5 ,
|
|
SSL_CK_RC4_128_EXPORT40_WITH_MD5 ,
|
|
SSL_CK_RC2_128_CBC_WITH_MD5 ,
|
|
SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 ,
|
|
SSL_CK_IDEA_128_CBC_WITH_MD5 ,
|
|
SSL_CK_DES_64_CBC_WITH_MD5 ,
|
|
SSL_CK_DES_192_EDE3_CBC_WITH_MD5 ,
|
|
SSL_CK_NULL_WITH_MD5 ,
|
|
SSL_CK_DES_64_CBC_WITH_SHA ,
|
|
SSL_CK_DES_192_EDE3_WITH_SHA };
|
|
|
|
|
|
#define SIZEOF(pMessage) (SslRecordSize((PSsl_Record_Header) pMessage ) )
|
|
|
|
DWORD
|
|
SslRecordSize(
|
|
PSsl_Record_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);
|
|
}
|
|
|
|
VOID
|
|
InitializeCipherMappings(VOID)
|
|
{
|
|
DWORD i;
|
|
DWORD FastForm;
|
|
|
|
cMappings = 10;
|
|
|
|
pCKMappings = SslAlloc('1 MC', LMEM_FIXED, cMappings * sizeof(CipherMapping));
|
|
SslAvailableCiphers = SslAlloc('2 MC', LMEM_FIXED, cMappings * sizeof(DWORD));
|
|
|
|
//
|
|
// FOR EXPORT, THIS IS EXACTLY 1 RIGHT NOW
|
|
//
|
|
|
|
|
|
|
|
for (i = 0; i < cMappings ; i++)
|
|
{
|
|
FastForm = (DWORD) MappingInitVector[i].C1 << 16 |
|
|
(DWORD) MappingInitVector[i].C2 << 8 |
|
|
(DWORD) MappingInitVector[i].C3 ;
|
|
|
|
pCKMappings[i].FastForm = FastForm;
|
|
pCKMappings[i].ThreeByteForm = MappingInitVector[i];
|
|
}
|
|
|
|
#ifdef SSL_DOMESTIC
|
|
|
|
SslNumberAvailableCiphers = 2;
|
|
SslAvailableCiphers[0] = 0x00010080;
|
|
SslAvailableCiphers[1] = 0x00020080;
|
|
|
|
#else
|
|
|
|
SslNumberAvailableCiphers = 1;
|
|
SslAvailableCiphers[0] = 0x00020080;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
BOOL
|
|
MapCipherToExternal(
|
|
DWORD FastForm,
|
|
PSsl_Cipher_Tuple pTuple)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; i < cMappings ; i++ )
|
|
{
|
|
if (pCKMappings[i].FastForm == FastForm)
|
|
{
|
|
*pTuple = pCKMappings[i].ThreeByteForm;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
DWORD
|
|
MapCipherFromExternal(
|
|
PSsl_Cipher_Tuple pTuple)
|
|
{
|
|
DWORD FastForm;
|
|
|
|
FastForm = (DWORD) pTuple->C1 << 16 |
|
|
(DWORD) pTuple->C2 << 8 |
|
|
(DWORD) pTuple->C3;
|
|
|
|
return(FastForm);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
PackClientHello(
|
|
PClient_Hello pCanonical,
|
|
PSsl_Client_Hello * ppNetwork,
|
|
DWORD * pcbNetwork)
|
|
{
|
|
DWORD TotalSpace;
|
|
DWORD MessageLength;
|
|
PSsl_Client_Hello pMessage;
|
|
DWORD Size;
|
|
PUCHAR pBuffer;
|
|
DWORD i;
|
|
|
|
|
|
MessageLength = pCanonical->SessionId.cbSessionId +
|
|
pCanonical->Challenge.cbChallenge +
|
|
pCanonical->cCipherSpecs * sizeof(Ssl_Cipher_Tuple) +
|
|
sizeof(Ssl_Client_Hello) -
|
|
(sizeof(Ssl_Record_Header) + 1 );
|
|
|
|
TotalSpace = MessageLength + 2;
|
|
|
|
if (*pcbNetwork)
|
|
{
|
|
if (*pcbNetwork < TotalSpace)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
*pcbNetwork = TotalSpace;
|
|
|
|
if (!ppNetwork)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if (*ppNetwork)
|
|
{
|
|
pMessage = *ppNetwork;
|
|
}
|
|
else
|
|
{
|
|
pMessage = SslExternalAlloc(TotalSpace);
|
|
if (!pMessage)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
pMessage->MessageId = SSL_MT_CLIENT_HELLO;
|
|
pMessage->VersionMsb = SSL_CLIENT_VERSION_MSB;
|
|
pMessage->VersionLsb = SSL_CLIENT_VERSION_LSB;
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
Size = pCanonical->cCipherSpecs * sizeof(Ssl_Cipher_Tuple);
|
|
|
|
for (i = 0; i < pCanonical->cCipherSpecs ; i++ )
|
|
{
|
|
if (MapCipherToExternal(pCanonical->pCipherSpecs[i],
|
|
(PSsl_Cipher_Tuple) pBuffer) )
|
|
{
|
|
pBuffer += sizeof(Ssl_Cipher_Tuple);
|
|
}
|
|
else
|
|
{
|
|
Size -= sizeof(Ssl_Cipher_Tuple);
|
|
MessageLength -= sizeof(Ssl_Cipher_Tuple);
|
|
TotalSpace -= sizeof(Ssl_Cipher_Tuple);
|
|
}
|
|
}
|
|
|
|
*pcbNetwork = TotalSpace;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(MessageLength) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(MessageLength);
|
|
|
|
pMessage->CipherSpecsLenMsb = MSBOF(Size);
|
|
pMessage->CipherSpecsLenLsb = LSBOF(Size);
|
|
|
|
pMessage->SessionIdLenMsb = MSBOF(pCanonical->SessionId.cbSessionId);
|
|
pMessage->SessionIdLenLsb = LSBOF(pCanonical->SessionId.cbSessionId);
|
|
if (pCanonical->SessionId.cbSessionId)
|
|
{
|
|
CopyMemory( pBuffer,
|
|
pCanonical->SessionId.bSessionId,
|
|
pCanonical->SessionId.cbSessionId);
|
|
|
|
pBuffer += pCanonical->SessionId.cbSessionId;
|
|
}
|
|
|
|
pMessage->ChallengeLenMsb = MSBOF(pCanonical->Challenge.cbChallenge);
|
|
pMessage->ChallengeLenLsb = LSBOF(pCanonical->Challenge.cbChallenge);
|
|
if (pCanonical->Challenge.cbChallenge)
|
|
{
|
|
CopyMemory( pBuffer,
|
|
pCanonical->Challenge.bChallenge,
|
|
pCanonical->Challenge.cbChallenge);
|
|
|
|
pBuffer += pCanonical->Challenge.cbChallenge;
|
|
}
|
|
|
|
*ppNetwork = pMessage;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
UnpackClientHello(
|
|
BOOL SingleAlloc,
|
|
PSsl_Client_Hello pMessage,
|
|
DWORD cbMessage,
|
|
PClient_Hello * ppClient)
|
|
{
|
|
DWORD ReportedSize;
|
|
DWORD CipherSpecsSize;
|
|
DWORD cCipherSpecs;
|
|
PClient_Hello pCanonical;
|
|
PUCHAR pBuffer;
|
|
DWORD Size;
|
|
DWORD ValidRemainingSize;
|
|
DWORD i;
|
|
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
if (ReportedSize > cbMessage)
|
|
{
|
|
SetLastError((ULONG) SEC_E_INVALID_TOKEN);
|
|
return(FALSE);
|
|
}
|
|
|
|
*ppClient = NULL;
|
|
|
|
if ((pMessage->MessageId != SSL_MT_CLIENT_HELLO) ||
|
|
(pMessage->VersionMsb != SSL_CLIENT_VERSION_MSB) ||
|
|
(pMessage->VersionLsb != SSL_CLIENT_VERSION_LSB) )
|
|
{
|
|
SetLastError((ULONG) SEC_E_INVALID_TOKEN);
|
|
return(FALSE);
|
|
}
|
|
|
|
CipherSpecsSize = COMBINEBYTES( pMessage->CipherSpecsLenMsb,
|
|
pMessage->CipherSpecsLenLsb );
|
|
|
|
|
|
cCipherSpecs = CipherSpecsSize / sizeof(Ssl_Cipher_Tuple);
|
|
|
|
if (SingleAlloc)
|
|
{
|
|
pCanonical = SslAlloc('leHC', LMEM_FIXED | LMEM_ZEROINIT,
|
|
sizeof(Client_Hello) +
|
|
cCipherSpecs * sizeof(CipherSpec) );
|
|
|
|
if (!pCanonical)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
pCanonical->pCipherSpecs = (PCipherSpec) (pCanonical + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
pCanonical = SslAlloc('leHC', LMEM_FIXED | LMEM_ZEROINIT,
|
|
sizeof(Client_Hello) );
|
|
|
|
if (pCanonical)
|
|
{
|
|
pCanonical->pCipherSpecs = SslAlloc('lehC', LMEM_FIXED,
|
|
cCipherSpecs * sizeof(CipherSpec) );
|
|
|
|
if (!pCanonical->pCipherSpecs)
|
|
{
|
|
SslFree(pCanonical);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
ValidRemainingSize = cbMessage - sizeof(Ssl_Client_Hello) + 1;
|
|
|
|
|
|
pCanonical->cCipherSpecs = cCipherSpecs;
|
|
|
|
for (i = 0 ; i < cCipherSpecs ; i++ )
|
|
{
|
|
pCanonical->pCipherSpecs[i] = MapCipherFromExternal((PSsl_Cipher_Tuple)
|
|
pBuffer);
|
|
|
|
pBuffer += sizeof(Ssl_Cipher_Tuple);
|
|
}
|
|
|
|
Size = COMBINEBYTES( pMessage->SessionIdLenMsb,
|
|
pMessage->SessionIdLenLsb );
|
|
|
|
if ((Size >= 0) && (Size <= SSL_SESSION_ID_LEN))
|
|
{
|
|
CopyMemory( pCanonical->SessionId.bSessionId, pBuffer, Size);
|
|
|
|
|
|
pBuffer += Size;
|
|
|
|
}
|
|
else
|
|
{
|
|
SslFree( pCanonical );
|
|
DebugLog((DEB_TRACE, "Invalid SessionId Size in ClientHello: %d\n", Size));
|
|
return( FALSE );
|
|
}
|
|
|
|
pCanonical->SessionId.cbSessionId = Size;
|
|
|
|
Size = COMBINEBYTES( pMessage->ChallengeLenMsb,
|
|
pMessage->ChallengeLenLsb );
|
|
|
|
if ((Size > 0) && (Size <= SSL_MAX_CHALLENGE_LEN))
|
|
{
|
|
CopyMemory( pCanonical->Challenge.bChallenge, pBuffer, Size );
|
|
|
|
pBuffer += Size;
|
|
}
|
|
else
|
|
{
|
|
SslFree( pCanonical );
|
|
DebugLog((DEB_TRACE, "Invalid Challenge Size in ClientHello: %d\n", Size));
|
|
return( FALSE );
|
|
}
|
|
|
|
pCanonical->Challenge.cbChallenge = Size;
|
|
|
|
*ppClient = pCanonical;
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOL
|
|
PackServerHello(
|
|
PServer_Hello pCanonical,
|
|
PSsl_Server_Hello * ppNetwork,
|
|
DWORD * pcbNetwork)
|
|
{
|
|
DWORD TotalSpace;
|
|
DWORD MessageLength;
|
|
PSsl_Server_Hello pMessage;
|
|
DWORD Size;
|
|
PUCHAR pBuffer;
|
|
DWORD i;
|
|
|
|
|
|
MessageLength = pCanonical->Connection.cbSessionId +
|
|
pCanonical->CertificateLength +
|
|
pCanonical->cCipherSpecs * sizeof(Ssl_Cipher_Tuple) +
|
|
sizeof(Ssl_Server_Hello) -
|
|
(sizeof(Ssl_Record_Header) + 1 );
|
|
|
|
TotalSpace = MessageLength + 2;
|
|
|
|
if (*pcbNetwork)
|
|
{
|
|
if (*pcbNetwork < TotalSpace)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
*pcbNetwork = TotalSpace;
|
|
|
|
if (!ppNetwork)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if (*ppNetwork)
|
|
{
|
|
pMessage = *ppNetwork;
|
|
}
|
|
else
|
|
{
|
|
pMessage = SslExternalAlloc( TotalSpace );
|
|
if (!pMessage)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
pMessage->MessageId = SSL_MT_SERVER_HELLO;
|
|
pMessage->ServerVersionMsb = SSL_SERVER_VERSION_MSB;
|
|
pMessage->ServerVersionLsb = SSL_SERVER_VERSION_LSB;
|
|
pMessage->SessionIdHit = (UCHAR) pCanonical->SessionIdHit;
|
|
pMessage->CertificateType = (UCHAR) pCanonical->CertificateType;
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
//
|
|
// Pack certificate if present
|
|
//
|
|
|
|
pMessage->CertificateLenMsb = MSBOF(pCanonical->CertificateLength);
|
|
pMessage->CertificateLenLsb = LSBOF(pCanonical->CertificateLength);
|
|
|
|
if (pCanonical->CertificateLength)
|
|
{
|
|
CopyMemory( pBuffer,
|
|
pCanonical->pCertificate,
|
|
pCanonical->CertificateLength);
|
|
|
|
pBuffer += pCanonical->CertificateLength ;
|
|
}
|
|
|
|
Size = pCanonical->cCipherSpecs * sizeof(Ssl_Cipher_Tuple);
|
|
|
|
for (i = 0; i < pCanonical->cCipherSpecs ; i++ )
|
|
{
|
|
if (MapCipherToExternal(pCanonical->pCipherSpecs[i],
|
|
(PSsl_Cipher_Tuple) pBuffer) )
|
|
{
|
|
pBuffer += sizeof(Ssl_Cipher_Tuple);
|
|
}
|
|
else
|
|
{
|
|
Size -= sizeof(Ssl_Cipher_Tuple);
|
|
MessageLength -= sizeof(Ssl_Cipher_Tuple);
|
|
TotalSpace -= sizeof(Ssl_Cipher_Tuple);
|
|
}
|
|
}
|
|
|
|
*pcbNetwork = TotalSpace;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(MessageLength) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(MessageLength);
|
|
|
|
pMessage->CipherSpecsLenMsb = MSBOF(Size);
|
|
pMessage->CipherSpecsLenLsb = LSBOF(Size);
|
|
|
|
pMessage->ConnectionIdLenMsb = MSBOF(pCanonical->Connection.cbSessionId);
|
|
pMessage->ConnectionIdLenLsb = LSBOF(pCanonical->Connection.cbSessionId);
|
|
if (pCanonical->Connection.cbSessionId)
|
|
{
|
|
CopyMemory( pBuffer,
|
|
pCanonical->Connection.bSessionId,
|
|
pCanonical->Connection.cbSessionId);
|
|
|
|
pBuffer += pCanonical->Connection.cbSessionId;
|
|
}
|
|
|
|
*ppNetwork = pMessage;
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
UnpackServerHello(
|
|
BOOL SingleAlloc,
|
|
PSsl_Server_Hello pMessage,
|
|
DWORD cbMessage,
|
|
PServer_Hello * ppServer)
|
|
{
|
|
PServer_Hello pCanonical;
|
|
PUCHAR pBuffer;
|
|
DWORD cbCertificate;
|
|
DWORD cCipherSpecs;
|
|
DWORD cbConnId;
|
|
DWORD i;
|
|
DWORD ReportedSize;
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
if (ReportedSize > cbMessage)
|
|
{
|
|
DebugLog((DEB_WARN, "ReportedSize (%d, %#x) > actual size (%d, %#x)\n",
|
|
ReportedSize, ReportedSize, cbMessage, cbMessage));
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
*ppServer = NULL;
|
|
|
|
//
|
|
// Verify Header:
|
|
//
|
|
|
|
if ((pMessage->MessageId != SSL_MT_SERVER_HELLO) ||
|
|
(pMessage->ServerVersionMsb != SSL_SERVER_VERSION_MSB) ||
|
|
(pMessage->ServerVersionLsb != SSL_SERVER_VERSION_LSB) )
|
|
{
|
|
SetLastError((ULONG) SEC_E_INVALID_TOKEN);
|
|
return(FALSE);
|
|
}
|
|
|
|
cbCertificate = COMBINEBYTES( pMessage->CertificateLenMsb,
|
|
pMessage->CertificateLenLsb);
|
|
|
|
cCipherSpecs = COMBINEBYTES(pMessage->CipherSpecsLenMsb,
|
|
pMessage->CipherSpecsLenLsb);
|
|
|
|
cCipherSpecs /= sizeof(Ssl_Cipher_Tuple);
|
|
|
|
cbConnId = COMBINEBYTES(pMessage->ConnectionIdLenMsb,
|
|
pMessage->ConnectionIdLenLsb);
|
|
|
|
if (SingleAlloc)
|
|
{
|
|
pCanonical = SslAlloc('lehS', LMEM_FIXED, sizeof(Server_Hello) +
|
|
cbCertificate + cbConnId +
|
|
cCipherSpecs * sizeof(CipherSpec) );
|
|
|
|
if (!pCanonical)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Set up pointers to be in this memory allocation.
|
|
//
|
|
|
|
pCanonical->pCipherSpecs = (PCipherSpec) (pCanonical + 1);
|
|
pCanonical->pCertificate = (PUCHAR) (pCanonical->pCipherSpecs + cCipherSpecs);
|
|
|
|
}
|
|
else
|
|
{
|
|
pCanonical = SslAlloc('lehS', LMEM_FIXED, sizeof(Server_Hello));
|
|
if (pCanonical)
|
|
{
|
|
pCanonical->pCertificate = SslAlloc('lehS', LMEM_FIXED, cbCertificate);
|
|
pCanonical->pCipherSpecs = SslAlloc('lehS', LMEM_FIXED,
|
|
cCipherSpecs * sizeof(CipherSpec) );
|
|
}
|
|
|
|
if (!pCanonical ||
|
|
!pCanonical->pCertificate ||
|
|
!pCanonical->pCipherSpecs)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Expand out:
|
|
//
|
|
|
|
pCanonical->SessionIdHit = (DWORD) pMessage->SessionIdHit;
|
|
pCanonical->CertificateType = (DWORD) pMessage->CertificateType;
|
|
pCanonical->CertificateLength = cbCertificate;
|
|
pCanonical->cCipherSpecs = cCipherSpecs;
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
CopyMemory(pCanonical->pCertificate, pBuffer, cbCertificate);
|
|
pBuffer += cbCertificate;
|
|
|
|
for (i = 0 ; i < cCipherSpecs ; i++ )
|
|
{
|
|
pCanonical->pCipherSpecs[i] = MapCipherFromExternal((PSsl_Cipher_Tuple)
|
|
pBuffer);
|
|
|
|
pBuffer += sizeof(Ssl_Cipher_Tuple);
|
|
}
|
|
|
|
pCanonical->Connection.cbSessionId = cbConnId;
|
|
|
|
if ((cbConnId) && (cbConnId <= SSL_SESSION_ID_LEN))
|
|
{
|
|
CopyMemory(pCanonical->Connection.bSessionId, pBuffer, cbConnId);
|
|
}
|
|
|
|
*ppServer = pCanonical;
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
BOOL
|
|
PackClientMasterKey(
|
|
PClient_Master_Key pCanonical,
|
|
PSsl_Client_Master_Key *ppNetwork,
|
|
DWORD * pcbNetwork)
|
|
{
|
|
DWORD MessageLength;
|
|
DWORD TotalSpace;
|
|
PSsl_Client_Master_Key pMessage;
|
|
PUCHAR pBuffer;
|
|
|
|
MessageLength = pCanonical->ClearKeyLen +
|
|
pCanonical->EncryptedKeyLen +
|
|
pCanonical->KeyArgLen +
|
|
sizeof(Ssl_Client_Master_Key) -
|
|
(sizeof(Ssl_Record_Header) + 1) ;
|
|
|
|
TotalSpace = MessageLength + 2;
|
|
|
|
if (*pcbNetwork)
|
|
{
|
|
if (*pcbNetwork < TotalSpace)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
*pcbNetwork = TotalSpace;
|
|
|
|
if (!ppNetwork)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if (*ppNetwork)
|
|
{
|
|
pMessage = *ppNetwork;
|
|
}
|
|
else
|
|
{
|
|
pMessage = SslExternalAlloc(TotalSpace);
|
|
if (!pMessage)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
pMessage->Header.Byte0 = MSBOF(MessageLength) | 0x80;
|
|
pMessage->Header.Byte1 = LSBOF(MessageLength);
|
|
|
|
pMessage->MessageId = SSL_MT_CLIENT_MASTER_KEY;
|
|
MapCipherToExternal(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->EncryptedKey, pCanonical->EncryptedKeyLen);
|
|
pBuffer += pCanonical->EncryptedKeyLen;
|
|
|
|
pMessage->KeyArgLenMsb = MSBOF(pCanonical->KeyArgLen);
|
|
pMessage->KeyArgLenLsb = LSBOF(pCanonical->KeyArgLen);
|
|
|
|
CopyMemory(pBuffer, pCanonical->KeyArg, pCanonical->KeyArgLen);
|
|
|
|
*ppNetwork = pMessage;
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
UnpackClientMasterKey(
|
|
PSsl_Client_Master_Key pMessage,
|
|
DWORD cbMessage,
|
|
PClient_Master_Key * ppClient)
|
|
{
|
|
PClient_Master_Key pCanonical;
|
|
PUCHAR pBuffer;
|
|
DWORD ReportedSize;
|
|
|
|
ReportedSize = SIZEOF(pMessage);
|
|
if (ReportedSize > cbMessage)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
*ppClient = NULL;
|
|
|
|
if ((pMessage->MessageId != SSL_MT_CLIENT_MASTER_KEY))
|
|
{
|
|
SetLastError((ULONG) SEC_E_INVALID_TOKEN);
|
|
return(FALSE);
|
|
}
|
|
|
|
pCanonical = SslAlloc('yKMC', LMEM_FIXED | LMEM_ZEROINIT,
|
|
sizeof(Client_Master_Key) );
|
|
|
|
if (!pCanonical)
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
pCanonical->CipherKind = MapCipherFromExternal( &pMessage->CipherKind );
|
|
pCanonical->ClearKeyLen = COMBINEBYTES( pMessage->ClearKeyLenMsb,
|
|
pMessage->ClearKeyLenLsb );
|
|
|
|
pCanonical->EncryptedKeyLen = COMBINEBYTES( pMessage->EncryptedKeyLenMsb,
|
|
pMessage->EncryptedKeyLenLsb );
|
|
|
|
pCanonical->KeyArgLen = COMBINEBYTES( pMessage->KeyArgLenMsb,
|
|
pMessage->KeyArgLenLsb );
|
|
|
|
|
|
//
|
|
// Validate
|
|
//
|
|
|
|
if ((pCanonical->ClearKeyLen > cbMessage) ||
|
|
(pCanonical->ClearKeyLen > MASTER_KEY_SIZE))
|
|
{
|
|
SslFree( pCanonical );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ((pCanonical->EncryptedKeyLen > cbMessage) ||
|
|
(pCanonical->EncryptedKeyLen > ENCRYPTED_KEY_SIZE))
|
|
{
|
|
SslFree( pCanonical );
|
|
return( FALSE );
|
|
}
|
|
|
|
if ((pCanonical->KeyArgLen > cbMessage) ||
|
|
(pCanonical->KeyArgLen > MASTER_KEY_SIZE))
|
|
{
|
|
SslFree( pCanonical );
|
|
return( FALSE );
|
|
}
|
|
|
|
pBuffer = pMessage->VariantData;
|
|
|
|
CopyMemory(pCanonical->ClearKey, pBuffer, pCanonical->ClearKeyLen );
|
|
|
|
pBuffer += pCanonical->ClearKeyLen;
|
|
|
|
CopyMemory(pCanonical->EncryptedKey, pBuffer, pCanonical->EncryptedKeyLen );
|
|
|
|
pBuffer += pCanonical->EncryptedKeyLen;
|
|
|
|
CopyMemory( pCanonical->KeyArg, pBuffer, pCanonical->KeyArgLen );
|
|
|
|
*ppClient = pCanonical;
|
|
|
|
return( TRUE );
|
|
}
|