//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: pct1pckl.c // // Contents: // // Classes: // // Functions: // // History: // //---------------------------------------------------------------------------- #include #include #include #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 ); }