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.
2186 lines
74 KiB
2186 lines
74 KiB
/*++
|
|
|
|
Copyright (c) 1998-99 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cliprot.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Frederick Chong (fredch) 6/1/1998
|
|
|
|
Environment:
|
|
|
|
Win32, WinCE, Win16
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include "windows.h"
|
|
#ifndef OS_WINCE
|
|
#include "stdio.h"
|
|
#endif // OS_WINCE
|
|
#include "stdlib.h"
|
|
|
|
#ifdef OS_WINCE
|
|
#include "wincelic.h"
|
|
#endif //OS_WINCE
|
|
|
|
#include "tchar.h"
|
|
|
|
#include "lmcons.h"
|
|
|
|
#include "seccom.h"
|
|
|
|
#include "cryptkey.h"
|
|
#include "hccontxt.h"
|
|
#include "cliprot.h"
|
|
#include "hcpack.h"
|
|
#include "store.h"
|
|
#include "licdbg.h"
|
|
#include "platform.h"
|
|
#include "licecert.h"
|
|
|
|
#ifdef _WIN64
|
|
|
|
#define OFFSET_OF(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field))
|
|
|
|
#else
|
|
|
|
#define OFFSET_OF(type, field) ((LONG)(LONG *)&(((type *)0)->field))
|
|
|
|
#endif
|
|
|
|
#define MAX_ALLOWABLE_LICENSE_SIZE (256 * 1024)
|
|
#define EXTENDED_ERROR_CAPABILITY 0x80
|
|
|
|
|
|
VOID
|
|
FreeProprietaryCertificate(
|
|
PHydra_Server_Cert * ppCertificate );
|
|
|
|
static BOOL GeneratePseudoLicense(DWORD FAR * pcbData , PBYTE *ppbData);
|
|
|
|
static LICENSE_STATUS MapStoreError(LS_STATUS lsStatus)
|
|
{
|
|
if(lsStatus == LSSTAT_SUCCESS)
|
|
return LICENSE_STATUS_OK;
|
|
if( (lsStatus == LSSTAT_ERROR) || (lsStatus == LSSTAT_INVALID_HANDLE) )
|
|
return LICENSE_STATUS_INVALID_INPUT;
|
|
if(lsStatus == LSSTAT_INSUFFICIENT_BUFFER)
|
|
return LICENSE_STATUS_INSUFFICIENT_BUFFER;
|
|
if(lsStatus == LSSTAT_LICENSE_NOT_FOUND)
|
|
return LICENSE_STATUS_NO_LICENSE_ERROR;
|
|
if(lsStatus == LSSTAT_OUT_OF_MEMORY)
|
|
return LICENSE_STATUS_OUT_OF_MEMORY;
|
|
if(lsStatus == LSSTAT_LICENSE_EXISTS)
|
|
return LICENSE_STATUS_DUPLICATE_LICENSE_ERROR;
|
|
|
|
return LICENSE_STATUS_INVALID_INPUT;
|
|
}
|
|
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
LicenseClientHandleServerMessage(
|
|
PLicense_Client_Context pContext,
|
|
UINT32 *puiExtendedErrorInfo,
|
|
BYTE FAR * pbInput,
|
|
DWORD cbInput,
|
|
BYTE FAR * pbOutput,
|
|
DWORD FAR * pcbOutput
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
BYTE FAR *pbTemp = NULL;
|
|
DWORD dwTemp = 0;
|
|
Preamble Header;
|
|
BOOL fNew = FALSE;
|
|
BOOL fSupportExtendedError = FALSE;
|
|
|
|
if(NULL == pContext || NULL == pbInput || pcbOutput == NULL)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
pbTemp = pbInput;
|
|
dwTemp = cbInput;
|
|
|
|
Header = *( UNALIGNED Preamble*)pbTemp;
|
|
|
|
//
|
|
// check if we can support this preamble version
|
|
//
|
|
|
|
if( Header.bVersion > LICENSE_CURRENT_PREAMBLE_VERSION )
|
|
{
|
|
lsReturn = LICENSE_STATUS_NOT_SUPPORTED;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
//
|
|
// Sets the preamble version to the version that the server is using
|
|
//
|
|
|
|
|
|
pContext->dwProtocolVersion |= Header.bVersion;
|
|
|
|
if(pContext->dwProtocolVersion >= 2)
|
|
{
|
|
fSupportExtendedError = TRUE;
|
|
}
|
|
|
|
if( Header.wMsgSize != dwTemp)
|
|
{
|
|
License_Error_Message Error;
|
|
memset(&Error, 0x00, sizeof(License_Error_Message));
|
|
Error.dwErrorCode = GM_HS_ERR_INVALID_MESSAGE_LEN;
|
|
Error.dwStateTransition = ST_RESEND_LAST_MESSAGE;
|
|
Error.bbErrorInfo.wBlobType = BB_ERROR_BLOB;
|
|
Error.bbErrorInfo.wBlobLen = 0;
|
|
Error.bbErrorInfo.pBlob = NULL;
|
|
|
|
DebugLog((DEB_TRACE, "Packing License Error Message from Client : %4d\n", *pcbOutput));
|
|
PackLicenseErrorMessage(&Error, fSupportExtendedError, pbOutput, pcbOutput);
|
|
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
pbTemp += sizeof(Preamble);
|
|
dwTemp -= sizeof(Preamble);
|
|
|
|
switch(Header.bMsgType)
|
|
{
|
|
case GM_ERROR_ALERT:
|
|
{
|
|
License_Error_Message Error;
|
|
|
|
memset(&Error, 0x00, sizeof(License_Error_Message));
|
|
|
|
DebugLog((DEB_TRACE, "Unpacking Hydra Server Error Message of size: %4d\n", dwTemp));
|
|
if( LICENSE_STATUS_OK != (lsReturn = UnPackLicenseErrorMessage(pbTemp,
|
|
dwTemp,
|
|
&Error)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
DebugLog((DEB_TRACE, "LicenseClientHandleServerError : %4d\n", *pcbOutput));
|
|
lsReturn = LicenseClientHandleServerError(pContext,
|
|
&Error,
|
|
puiExtendedErrorInfo,
|
|
pbOutput,
|
|
pcbOutput);
|
|
if(Error.bbErrorInfo.pBlob)
|
|
{
|
|
free(Error.bbErrorInfo.pBlob);
|
|
Error.bbErrorInfo.pBlob = NULL;
|
|
}
|
|
#if DBG
|
|
if(pbOutput)
|
|
OutputDebugString(_T("Client response data : \n"));
|
|
LS_DUMPSTRING(*pcbOutput, pbOutput);
|
|
#endif
|
|
|
|
if( lsReturn == LICENSE_STATUS_OK ||
|
|
lsReturn == LICENSE_STATUS_CONTINUE ||
|
|
lsReturn == LICENSE_STATUS_CLIENT_ABORT ||
|
|
lsReturn == LICENSE_STATUS_SERVER_ABORT )
|
|
goto CommonReturn;
|
|
else
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case HS_LICENSE_REQUEST:
|
|
{
|
|
Hydra_Server_License_Request LicRequest;
|
|
DWORD dw;
|
|
|
|
memset(&LicRequest, 0x00, sizeof(Hydra_Server_License_Request));
|
|
|
|
DebugLog((DEB_TRACE, "Unpacking Hydra Server's License Request : %4d\n", dwTemp));
|
|
if( LICENSE_STATUS_OK != (lsReturn = UnpackHydraServerLicenseRequest(pbTemp,
|
|
dwTemp,
|
|
&LicRequest)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
DebugLog((DEB_TRACE, "Client handles Server's license Request : %4d\n", *pcbOutput));
|
|
|
|
lsReturn = LicenseClientHandleServerRequest(pContext,
|
|
&LicRequest,
|
|
TRUE,
|
|
pbOutput,
|
|
pcbOutput,
|
|
fSupportExtendedError);
|
|
#if DBG
|
|
if(pbOutput)
|
|
OutputDebugString(_T("Client response data : \n"));
|
|
LS_DUMPSTRING(*pcbOutput, pbOutput);
|
|
#endif
|
|
|
|
if(LicRequest.ProductInfo.pbCompanyName)
|
|
{
|
|
free(LicRequest.ProductInfo.pbCompanyName);
|
|
LicRequest.ProductInfo.pbCompanyName = NULL;
|
|
}
|
|
if(LicRequest.ProductInfo.pbProductID)
|
|
{
|
|
free(LicRequest.ProductInfo.pbProductID);
|
|
LicRequest.ProductInfo.pbProductID = NULL;
|
|
}
|
|
|
|
for(dw = 0; dw <LicRequest.ScopeList.dwScopeCount; dw++)
|
|
{
|
|
if(LicRequest.ScopeList.Scopes[dw].pBlob)
|
|
{
|
|
free(LicRequest.ScopeList.Scopes[dw].pBlob);
|
|
LicRequest.ScopeList.Scopes[dw].pBlob = NULL;
|
|
}
|
|
}
|
|
|
|
if(LicRequest.ScopeList.Scopes)
|
|
{
|
|
free(LicRequest.ScopeList.Scopes);
|
|
LicRequest.ScopeList.Scopes = NULL;
|
|
}
|
|
|
|
if( LicRequest.KeyExchngList.pBlob )
|
|
{
|
|
free( LicRequest.KeyExchngList.pBlob );
|
|
}
|
|
|
|
if( LicRequest.ServerCert.pBlob )
|
|
{
|
|
free( LicRequest.ServerCert.pBlob );
|
|
}
|
|
|
|
if( lsReturn != LICENSE_STATUS_OK &&
|
|
lsReturn != LICENSE_STATUS_CONTINUE &&
|
|
lsReturn != LICENSE_STATUS_CLIENT_ABORT )
|
|
{
|
|
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
break;
|
|
}
|
|
case HS_PLATFORM_CHALLENGE:
|
|
{
|
|
Hydra_Server_Platform_Challenge PlatformCh;
|
|
memset(&PlatformCh, 0x00, sizeof(Hydra_Server_Platform_Challenge));
|
|
|
|
DebugLog((DEB_TRACE, "Unpacking Hydra Server's platform Challenge Request : %4d\n", dwTemp));
|
|
if( LICENSE_STATUS_OK != (lsReturn = UnPackHydraServerPlatformChallenge(pbTemp,
|
|
dwTemp,
|
|
&PlatformCh)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
DebugLog((DEB_TRACE, "Client Handles Server's platform Challenge Response : %0d\n", *pcbOutput));
|
|
lsReturn = LicenseClientHandleServerPlatformChallenge(pContext,
|
|
&PlatformCh,
|
|
pbOutput,
|
|
pcbOutput,
|
|
fSupportExtendedError);
|
|
#if DBG
|
|
if(pbOutput)
|
|
OutputDebugString(_T("Client response data : \n"));
|
|
LS_DUMPSTRING(*pcbOutput, pbOutput);
|
|
#endif
|
|
|
|
if(PlatformCh.EncryptedPlatformChallenge.pBlob)
|
|
{
|
|
free(PlatformCh.EncryptedPlatformChallenge.pBlob);
|
|
PlatformCh.EncryptedPlatformChallenge.pBlob = NULL;
|
|
}
|
|
|
|
if( lsReturn!=LICENSE_STATUS_CONTINUE )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case HS_NEW_LICENSE:
|
|
fNew = TRUE;
|
|
DebugLog((DEB_TRACE, "New License received from Server.\n"));
|
|
case HS_UPGRADE_LICENSE:
|
|
{
|
|
Hydra_Server_New_License NewLicense;
|
|
|
|
if (dwTemp > MAX_ALLOWABLE_LICENSE_SIZE)
|
|
{
|
|
//
|
|
// SECURITY: Too much data to store in the registry
|
|
// Reject the message
|
|
//
|
|
|
|
LS_LOG_RESULT(lsReturn = LICENSE_STATUS_INVALID_INPUT);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&NewLicense, 0x00, sizeof(Hydra_Server_New_License));
|
|
|
|
|
|
DebugLog((DEB_TRACE, "Unpacking Hydra Server's New License Message : %4d\n", dwTemp));
|
|
|
|
if(LICENSE_STATUS_OK !=
|
|
(lsReturn = UnPackHydraServerNewLicense(pbTemp,
|
|
dwTemp,
|
|
&NewLicense)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
DebugLog((DEB_TRACE, "License Client handles New License : %4d\n", *pcbOutput));
|
|
lsReturn = LicenseClientHandleNewLicense(pContext,
|
|
&NewLicense,
|
|
fNew,
|
|
pbOutput,
|
|
pcbOutput);
|
|
|
|
|
|
if(NewLicense.EncryptedNewLicenseInfo.pBlob)
|
|
{
|
|
free(NewLicense.EncryptedNewLicenseInfo.pBlob);
|
|
NewLicense.EncryptedNewLicenseInfo.pBlob = NULL;
|
|
}
|
|
|
|
#if DBG
|
|
if(pbOutput)
|
|
OutputDebugString(_T("Client response data : \n"));
|
|
LS_DUMPSTRING(*pcbOutput, pbOutput);
|
|
#endif
|
|
|
|
if( lsReturn != LICENSE_STATUS_OK )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
//
|
|
// Invalid message type
|
|
//
|
|
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
goto ErrorReturn;
|
|
break;
|
|
}
|
|
LS_LOG_RESULT(lsReturn);
|
|
|
|
CommonReturn:
|
|
|
|
return lsReturn;
|
|
LS_RETURN(lsReturn);
|
|
|
|
ErrorReturn:
|
|
*pcbOutput = 0;
|
|
|
|
goto CommonReturn;
|
|
}
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
LicenseClientHandleServerError(
|
|
PLicense_Client_Context pContext,
|
|
PLicense_Error_Message pCanonical,
|
|
UINT32 *puiExtendedErrorInfo,
|
|
BYTE FAR * pbMessage,
|
|
DWORD FAR * pcbMessage
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
LS_BEGIN(TEXT("LicenseClientHandleServerError"));
|
|
|
|
if(NULL == pContext || NULL == pCanonical || NULL == pcbMessage || NULL == puiExtendedErrorInfo)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
return lsReturn;
|
|
}
|
|
|
|
// Switch on the StateTransition as this dictates the next state
|
|
// client has to take!
|
|
|
|
switch(pCanonical->dwStateTransition)
|
|
{
|
|
|
|
case ST_TOTAL_ABORT: //Server has asked for a total abort
|
|
*pcbMessage = 0;
|
|
if( pCanonical->dwErrorCode == GM_HS_ERR_INVALID_CLIENT ||
|
|
pCanonical->dwErrorCode == GM_HS_ERR_INVALID_SCOPE ||
|
|
pCanonical->dwErrorCode == GM_HS_ERR_INVALID_PRODUCTID ||
|
|
pCanonical->dwErrorCode == GM_HS_ERR_INVALID_CLIENT )
|
|
{
|
|
lsReturn = LICENSE_STATUS_SERVER_ABORT;
|
|
}
|
|
else
|
|
lsReturn = LICENSE_STATUS_CLIENT_ABORT;
|
|
|
|
pContext->dwState = LICENSE_CLIENT_STATE_ABORT;
|
|
pContext->cbLastMessage = 0;
|
|
break;
|
|
|
|
case ST_NO_TRANSITION:
|
|
lsReturn = LICENSE_STATUS_OK;
|
|
*pcbMessage = 0;
|
|
break;
|
|
|
|
case ST_RESEND_LAST_MESSAGE:
|
|
// Server has asked to send the last send message again!
|
|
// treat as error (fall through)
|
|
|
|
case ST_RESET_PHASE_TO_START:
|
|
// Server has asked to restart the negotiation
|
|
// treat as error (fall through)
|
|
|
|
default:
|
|
// Server sent unknown dwStateTransition
|
|
|
|
lsReturn = LICENSE_STATUS_CLIENT_ABORT;
|
|
pContext->dwState = LICENSE_CLIENT_STATE_ABORT;
|
|
pContext->cbLastMessage = 0;
|
|
break;
|
|
|
|
}
|
|
|
|
if ((lsReturn != LICENSE_STATUS_OK) && (pCanonical->bbErrorInfo.wBlobLen > 0) && (pCanonical->bbErrorInfo.pBlob != NULL))
|
|
{
|
|
// ignore any errors
|
|
|
|
UnPackExtendedErrorInfo(puiExtendedErrorInfo,&(pCanonical->bbErrorInfo));
|
|
}
|
|
|
|
LS_LOG_RESULT(lsReturn);
|
|
return lsReturn;
|
|
}
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
LicenseClientHandleServerRequest(
|
|
PLicense_Client_Context pContext,
|
|
PHydra_Server_License_Request pCanonical,
|
|
BOOL fNewLicense,
|
|
BYTE FAR * pbMessage,
|
|
DWORD FAR * pcbMessage,
|
|
BOOL fExtendedError
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
UCHAR Random[LICENSE_RANDOM];
|
|
UCHAR PreMasterSecret[LICENSE_PRE_MASTER_SECRET];
|
|
HANDLE hStore = NULL;
|
|
LSINDEX lsIndex;
|
|
DWORD dwCount = 0;
|
|
BYTE FAR * pbData = NULL;
|
|
DWORD cbData = 0;
|
|
|
|
LS_BEGIN(TEXT("LicenseClientHandleServerRequest"));
|
|
|
|
memset(&lsIndex, 0x00, sizeof(LSINDEX));
|
|
|
|
|
|
if( (pContext == NULL) || (pCanonical == NULL) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if(pContext->dwState != LICENSE_CLIENT_STATE_WAIT_SERVER_HELLO)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_CLIENT_STATE;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if( pContext->dwContextFlags & LICENSE_CONTEXT_NO_SERVER_AUTHENTICATION )
|
|
{
|
|
//
|
|
// No server authentication required, make sure that we have the
|
|
// public key or the certificate of the server so that we can use it to
|
|
// encrypt the pre-master secret during the next phase of the licensing protocol.
|
|
//
|
|
|
|
if( ( NULL == pContext->pbServerPubKey ) && ( NULL == pContext->pServerCert ) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_CONTEXT_INITIALIZATION_ERROR;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do Hydra server authentication by validating the server certificate
|
|
//
|
|
|
|
DWORD
|
|
dwCertVersion;
|
|
|
|
if( ( 0 >= pCanonical->ServerCert.wBlobLen ) ||
|
|
( NULL == pCanonical->ServerCert.pBlob ) )
|
|
{
|
|
//
|
|
// make sure that we have received a certificate from the server
|
|
//
|
|
|
|
lsReturn = LICENSE_STATUS_NO_CERTIFICATE;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Determine the version of the certificate so that we can decode and
|
|
// validate it correctly.
|
|
//
|
|
|
|
memcpy( ( char * )&dwCertVersion, pCanonical->ServerCert.pBlob, sizeof( DWORD ) );
|
|
|
|
if( CERT_CHAIN_VERSION_2 > dwCertVersion )
|
|
{
|
|
Hydra_Server_Cert ServerCert;
|
|
|
|
//
|
|
// Validate a proprietory certificate
|
|
//
|
|
|
|
memset( &ServerCert, 0, sizeof( ServerCert ) );
|
|
|
|
if( !UnpackServerCert(pCanonical->ServerCert.pBlob,
|
|
(DWORD)pCanonical->ServerCert.wBlobLen,
|
|
&ServerCert) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_UNSPECIFIED_ERROR;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Now verify the signature on the server certificate
|
|
|
|
if(!ValidateServerCert(&ServerCert) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_UNSPECIFIED_ERROR;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// free any old certificate and remember the new one.
|
|
//
|
|
|
|
if( pContext->pServerCert )
|
|
{
|
|
FreeProprietaryCertificate( &pContext->pServerCert );
|
|
}
|
|
|
|
lsReturn = LicenseSetCertificate(
|
|
( HANDLE )pContext,
|
|
&ServerCert );
|
|
|
|
if( LICENSE_STATUS_OK != lsReturn )
|
|
{
|
|
LS_LOG_RESULT( lsReturn );
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD
|
|
fDates = CERT_DATE_DONT_VALIDATE;
|
|
|
|
//
|
|
// X509 certificate
|
|
//
|
|
|
|
//
|
|
// this first call finds out the memory required for the public key
|
|
//
|
|
|
|
lsReturn = VerifyCertChain( pCanonical->ServerCert.pBlob,
|
|
( DWORD )pCanonical->ServerCert.wBlobLen,
|
|
NULL,
|
|
&pContext->cbServerPubKey,
|
|
&fDates );
|
|
|
|
if( LICENSE_STATUS_INSUFFICIENT_BUFFER == lsReturn )
|
|
{
|
|
if( pContext->pbServerPubKey )
|
|
{
|
|
free( pContext->pbServerPubKey );
|
|
}
|
|
|
|
pContext->pbServerPubKey = malloc( pContext->cbServerPubKey );
|
|
|
|
if( NULL == pContext->pbServerPubKey )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
lsReturn = VerifyCertChain( pCanonical->ServerCert.pBlob,
|
|
( DWORD )pCanonical->ServerCert.wBlobLen,
|
|
pContext->pbServerPubKey,
|
|
&pContext->cbServerPubKey,
|
|
&fDates );
|
|
}
|
|
|
|
if( LICENSE_STATUS_OK != lsReturn )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pContext->pCryptParam == NULL)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INITIALIZATION_FAILED;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Copy Server Random to pCryptSystem->rgbServerRandom
|
|
memcpy(pContext->pCryptParam->rgbServerRandom, pCanonical->ServerRandom, LICENSE_RANDOM);
|
|
|
|
LicenseDebugOutput("Server Random : \n");
|
|
LS_DUMPSTRING(LICENSE_RANDOM, pContext->pCryptParam->rgbServerRandom);
|
|
|
|
//Generate 32 byte Client Random
|
|
if (!TSRNG_GenerateRandomBits(Random, LICENSE_RANDOM))
|
|
{
|
|
lsReturn = LICENSE_STATUS_CONTEXT_INITIALIZATION_ERROR;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Copy ClientRandom to pContext->pCryptParam
|
|
memcpy(pContext->pCryptParam->rgbClientRandom, Random, LICENSE_RANDOM);
|
|
|
|
LicenseDebugOutput("Client Random : \n");
|
|
LS_DUMPSTRING(LICENSE_RANDOM, pContext->pCryptParam->rgbClientRandom);
|
|
|
|
//Generate 48 byte long PreMasterSecret
|
|
if (!TSRNG_GenerateRandomBits(PreMasterSecret, LICENSE_PRE_MASTER_SECRET))
|
|
{
|
|
lsReturn = LICENSE_STATUS_CONTEXT_INITIALIZATION_ERROR;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
LicenseDebugOutput("Pre Master Secret : \n");
|
|
LS_DUMPSTRING(LICENSE_PRE_MASTER_SECRET, PreMasterSecret);
|
|
|
|
//Copy Premastersecret to pCryptParam
|
|
lsReturn = LicenseSetPreMasterSecret(pContext->pCryptParam, PreMasterSecret);
|
|
|
|
|
|
//Search in the store to find an appropriate License
|
|
|
|
//To do that, first open the system store.
|
|
if( LICENSE_STATUS_OK != (lsReturn = MapStoreError(LSOpenLicenseStore(&hStore, NULL, TRUE))) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Initialize lsIndex structure with the values sent by the Server
|
|
lsIndex.dwVersion = pCanonical->ProductInfo.dwVersion;
|
|
lsIndex.cbCompany = pCanonical->ProductInfo.cbCompanyName;
|
|
|
|
if( NULL == (lsIndex.pbCompany = (LPSTR)malloc(lsIndex.cbCompany)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(lsIndex.pbCompany, 0x00, lsIndex.cbCompany);
|
|
memcpy(lsIndex.pbCompany, pCanonical->ProductInfo.pbCompanyName, lsIndex.cbCompany);
|
|
|
|
lsIndex.cbProductID = pCanonical->ProductInfo.cbProductID;
|
|
|
|
if( NULL == (lsIndex.pbProductID = (LPSTR)malloc(lsIndex.cbProductID)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(lsIndex.pbProductID, 0x00, lsIndex.cbProductID);
|
|
memcpy(lsIndex.pbProductID, pCanonical->ProductInfo.pbProductID, lsIndex.cbProductID );
|
|
|
|
for(dwCount=0; dwCount<pCanonical->ScopeList.dwScopeCount; dwCount ++)
|
|
{
|
|
DWORD dwProtVer = PREAMBLE_VERSION_1_0;
|
|
lsIndex.cbScope = pCanonical->ScopeList.Scopes[dwCount].wBlobLen;
|
|
if( NULL == (lsIndex.pbScope = (LPSTR)malloc(lsIndex.cbScope)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
continue;
|
|
}
|
|
|
|
//Initialize pszScope member of the lsIndex with the ith element in the scopelist
|
|
memset(lsIndex.pbScope, 0x00, lsIndex.cbScope);
|
|
memcpy(lsIndex.pbScope, pCanonical->ScopeList.Scopes[dwCount].pBlob, lsIndex.cbScope);
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = MapStoreError(LSFindLicenseInStore(hStore,
|
|
&lsIndex,
|
|
&cbData,
|
|
NULL))) )
|
|
{
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// NOTE: this line was previously
|
|
// if(pContext->dwProtocolVersion != PREAMBLE_VERSION_2_0) for
|
|
// Hydra 4.0 clients, which means that a pseudo license will be
|
|
// generated for licensing protocol later than 2.0 as well!
|
|
// To overcome this problem, Hydra 5.0 server will use the
|
|
// PREAMBLE_VERSION_2_0 for Hydra 4.0 clients.
|
|
//
|
|
|
|
if( GET_PREAMBLE_VERSION( pContext->dwProtocolVersion ) < PREAMBLE_VERSION_2_0)
|
|
{
|
|
if( !GeneratePseudoLicense(&cbData, &pbData) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_UNSPECIFIED_ERROR;
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
goto ErrorReturn;
|
|
}
|
|
lsReturn = LICENSE_STATUS_OK;
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
break;
|
|
}
|
|
if(cbData == 0)
|
|
{
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
if( NULL == (pbData=(BYTE FAR *)malloc(cbData)) )
|
|
{
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
continue;
|
|
}
|
|
if( LICENSE_STATUS_OK != (lsReturn = MapStoreError(LSFindLicenseInStore(hStore,
|
|
&lsIndex,
|
|
&cbData,
|
|
pbData))) )
|
|
{
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
LicenseDebugOutput("License Info Data : \n");
|
|
LS_DUMPSTRING(cbData, pbData);
|
|
|
|
lsReturn = LICENSE_STATUS_OK;
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//If a license is found in the store, then Continue with Hydra_Client_License_Info message
|
|
if( LICENSE_STATUS_OK == lsReturn )
|
|
{
|
|
if( LICENSE_STATUS_CONTINUE != (lsReturn = ClientConstructLicenseInfo(pContext,
|
|
pbData,
|
|
cbData,
|
|
pbMessage,
|
|
pcbMessage,
|
|
fExtendedError)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
goto CommonReturn;
|
|
}
|
|
|
|
//Else if no license if found, then depending on fNewLicense, either Request for a new license
|
|
//or, abort connection
|
|
|
|
else if(lsReturn == LICENSE_STATUS_NO_LICENSE_ERROR)
|
|
{
|
|
if(fNewLicense)
|
|
{
|
|
if( LICENSE_STATUS_CONTINUE != (lsReturn = ClientConstructNewLicenseRequest(pContext,
|
|
pbMessage,
|
|
pcbMessage,
|
|
fExtendedError)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
goto CommonReturn;
|
|
}
|
|
else //Generate an error message and close connection
|
|
{
|
|
if( LICENSE_STATUS_CLIENT_ABORT != (lsReturn = ClientConstructErrorAlert(pContext,
|
|
GM_HC_ERR_NO_LICENSE,
|
|
ST_TOTAL_ABORT,
|
|
NULL,
|
|
0,
|
|
pbMessage,
|
|
pcbMessage,
|
|
fExtendedError
|
|
)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
}
|
|
|
|
LS_LOG_RESULT(lsReturn);
|
|
|
|
CommonReturn:
|
|
|
|
//
|
|
// close license store
|
|
//
|
|
|
|
if( hStore )
|
|
{
|
|
LSCloseLicenseStore(hStore);
|
|
hStore = NULL;
|
|
}
|
|
|
|
if(pbData)
|
|
{
|
|
free(pbData);
|
|
pbData = NULL;
|
|
}
|
|
if(lsIndex.pbCompany)
|
|
{
|
|
free(lsIndex.pbCompany);
|
|
lsIndex.pbCompany = NULL;
|
|
}
|
|
if(lsIndex.pbProductID)
|
|
{
|
|
free(lsIndex.pbProductID);
|
|
lsIndex.pbProductID = NULL;
|
|
}
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
return lsReturn;
|
|
//LS_RETURN(lsReturn);
|
|
ErrorReturn:
|
|
*pcbMessage = 0;
|
|
|
|
if( pContext != NULL)
|
|
{
|
|
if(pContext->pServerCert)
|
|
{
|
|
free(pContext->pServerCert);
|
|
pContext->pServerCert = NULL;
|
|
}
|
|
|
|
if( pContext->pbServerPubKey )
|
|
{
|
|
free( pContext->pbServerPubKey );
|
|
pContext->pbServerPubKey = NULL;
|
|
}
|
|
}
|
|
|
|
goto CommonReturn;
|
|
}
|
|
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
LicenseClientHandleServerPlatformChallenge(
|
|
PLicense_Client_Context pContext,
|
|
PHydra_Server_Platform_Challenge pCanonical,
|
|
BYTE FAR * pbMessage,
|
|
DWORD FAR * pcbMessage,
|
|
BOOL fExtendedError
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
Hydra_Client_Platform_Challenge_Response Response;
|
|
|
|
BYTE MACData[LICENSE_MAC_DATA];
|
|
HWID hwid;
|
|
BYTE FAR * pbData = NULL;
|
|
UCHAR * LocalBuf = NULL;
|
|
DWORD cbData = 0;
|
|
|
|
LS_BEGIN(TEXT("LicenseClientHandleServerPlatformChallenge"));
|
|
|
|
|
|
if( (pContext == NULL) || (pCanonical == NULL) || (pcbMessage == NULL) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
memset(&Response, 0x00, sizeof(Hydra_Client_Platform_Challenge_Response));
|
|
|
|
|
|
if( (pContext->dwState != LICENSE_CLIENT_STATE_LICENSE_RESPONSE) &&
|
|
(pContext->dwState != LICENSE_CLIENT_STATE_NEW_LICENSE_REQUEST) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_CLIENT_STATE;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//First decrypt the encrypted platform challenge
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseDecryptSessionData(pContext->pCryptParam,
|
|
pCanonical->EncryptedPlatformChallenge.pBlob,
|
|
(DWORD)pCanonical->EncryptedPlatformChallenge.wBlobLen)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Generate the MAC with the decrypted platform Challenge
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseGenerateMAC(pContext->pCryptParam,
|
|
pCanonical->EncryptedPlatformChallenge.pBlob,
|
|
(DWORD)pCanonical->EncryptedPlatformChallenge.wBlobLen,
|
|
MACData
|
|
)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
LicenseDebugOutput(" Client generated MAC data to verify Server's message Authenticity : \n");
|
|
LS_DUMPSTRING(LICENSE_MAC_DATA, MACData);
|
|
|
|
|
|
//Compare the generated MAC with the one sent by the server
|
|
if( memcmp(MACData, pCanonical->MACData, LICENSE_MAC_DATA) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_MAC_DATA;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Generate Platform Challenge Response
|
|
if( LICENSE_STATUS_OK != (lsReturn = ClientGenerateChallengeResponse(pContext,
|
|
&pCanonical->EncryptedPlatformChallenge,
|
|
&Response.EncryptedChallengeResponse)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
|
|
}
|
|
|
|
//Generate HWID, Encrypt it using the Session key and put it in the Response
|
|
memset(&hwid, 0x00, sizeof(HWID));
|
|
if( LICENSE_STATUS_OK != (lsReturn = GenerateClientHWID(&hwid)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
//GenerateClientHWID(&hwid);
|
|
LicenseDebugOutput("HWID in byte : \n");
|
|
|
|
LS_DUMPSTRING(sizeof(HWID), (BYTE FAR *)&hwid);
|
|
|
|
|
|
Response.EncryptedHWID.wBlobType = BB_DATA_BLOB;
|
|
Response.EncryptedHWID.wBlobLen = sizeof(HWID);
|
|
if( NULL == (Response.EncryptedHWID.pBlob = (BYTE FAR *)malloc(Response.EncryptedHWID.wBlobLen)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(Response.EncryptedHWID.pBlob, 0x00, Response.EncryptedHWID.wBlobLen);
|
|
memcpy(Response.EncryptedHWID.pBlob, &hwid, Response.EncryptedHWID.wBlobLen);
|
|
|
|
if( NULL == (LocalBuf = (UCHAR *)malloc(Response.EncryptedChallengeResponse.wBlobLen +
|
|
Response.EncryptedHWID.wBlobLen)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
cbData += Response.EncryptedChallengeResponse.wBlobLen;
|
|
memcpy(LocalBuf, Response.EncryptedChallengeResponse.pBlob, Response.EncryptedChallengeResponse.wBlobLen);
|
|
memcpy(LocalBuf + cbData, Response.EncryptedHWID.pBlob, Response.EncryptedHWID.wBlobLen);
|
|
cbData += Response.EncryptedHWID.wBlobLen;
|
|
|
|
//Generate MACData and put it in the Response
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseGenerateMAC(pContext->pCryptParam,
|
|
LocalBuf,
|
|
cbData,
|
|
Response.MACData)) )
|
|
{
|
|
free(LocalBuf);
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
free(LocalBuf);
|
|
|
|
//Now encrypt the platform challenge response using the negotiated session key
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEncryptSessionData(pContext->pCryptParam,
|
|
Response.EncryptedChallengeResponse.pBlob,
|
|
Response.EncryptedChallengeResponse.wBlobLen
|
|
)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Encrypt the HWID with generated session key
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEncryptSessionData(pContext->pCryptParam,
|
|
Response.EncryptedHWID.pBlob,
|
|
(DWORD)Response.EncryptedHWID.wBlobLen)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Now we have our Platform challenge Response Ready. Pack the data in a byte stream
|
|
if( LICENSE_STATUS_OK != (lsReturn = PackHydraClientPlatformChallengeResponse(&Response,
|
|
fExtendedError,
|
|
pbMessage,
|
|
pcbMessage)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
// Set appropriate state and data in proper places
|
|
|
|
//Set the MACData in the CryptSystem MAC buffer.
|
|
memcpy(pContext->rgbMACData, Response.MACData, LICENSE_MAC_DATA);
|
|
|
|
//Set the state of the context to LICENSE_CLIENT_STATE_PLATFORM_CHALLENGE_RESPONSE
|
|
//provided data was written in the output. i.e pbMessage is not NULL
|
|
|
|
if(pbMessage)
|
|
pContext->dwState = LICENSE_CLIENT_STATE_PLATFORM_CHALLENGE_RESPONSE;
|
|
|
|
//Copy the whole message to the context
|
|
pContext->cbLastMessage = *pcbMessage;
|
|
if(pbMessage)
|
|
{
|
|
if( pContext->pbLastMessage )
|
|
{
|
|
free( pContext->pbLastMessage );
|
|
}
|
|
|
|
if( NULL == (pContext->pbLastMessage = (BYTE FAR *)malloc(pContext->cbLastMessage)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(pContext->pbLastMessage, 0x00, pContext->cbLastMessage);
|
|
memcpy(pContext->pbLastMessage, pbMessage, pContext->cbLastMessage);
|
|
}
|
|
|
|
lsReturn = LICENSE_STATUS_CONTINUE;
|
|
|
|
LS_LOG_RESULT(lsReturn);
|
|
CommonReturn:
|
|
//LICENSE_LOG_RESULT(lsReturn);
|
|
|
|
if(Response.EncryptedChallengeResponse.pBlob)
|
|
{
|
|
free(Response.EncryptedChallengeResponse.pBlob);
|
|
Response.EncryptedChallengeResponse.pBlob = NULL;
|
|
}
|
|
if(Response.EncryptedHWID.pBlob)
|
|
{
|
|
free(Response.EncryptedHWID.pBlob);
|
|
Response.EncryptedHWID.pBlob = NULL;
|
|
}
|
|
return lsReturn;
|
|
//LS_RETURN(lsReturn);
|
|
ErrorReturn:
|
|
*pcbMessage = 0;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
LicenseClientHandleNewLicense(
|
|
PLicense_Client_Context pContext,
|
|
PHydra_Server_New_License pCanonical,
|
|
BOOL fNew,
|
|
BYTE FAR * pbMessage,
|
|
DWORD FAR * pcbMessage
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
New_License_Info NewLicense;
|
|
BYTE MACData[LICENSE_MAC_DATA];
|
|
Binary_Blob bbData;
|
|
LSINDEX lsIndex;
|
|
HANDLE hStore = NULL;
|
|
|
|
LS_BEGIN(TEXT("LicenseClientHandleNewLicense"));
|
|
|
|
if(NULL == pContext || NULL == pCanonical )
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(&bbData, 0x00, sizeof(Binary_Blob));
|
|
memset(&NewLicense, 0x00, sizeof(New_License_Info));
|
|
memset(&lsIndex, 0x00, sizeof(LSINDEX));
|
|
|
|
//First decrypt the encrypted license info
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseDecryptSessionData(pContext->pCryptParam,
|
|
pCanonical->EncryptedNewLicenseInfo.pBlob,
|
|
( DWORD )( pCanonical->EncryptedNewLicenseInfo.wBlobLen ))) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Generate the MAC data with the decrypted data
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseGenerateMAC(pContext->pCryptParam,
|
|
pCanonical->EncryptedNewLicenseInfo.pBlob,
|
|
(DWORD)pCanonical->EncryptedNewLicenseInfo.wBlobLen,
|
|
MACData)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Compare this MAC with the one sent by the Server.
|
|
if(memcmp(MACData, pCanonical->MACData, LICENSE_MAC_DATA))
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_MAC_DATA;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = UnpackNewLicenseInfo(pCanonical->EncryptedNewLicenseInfo.pBlob,
|
|
(DWORD)pCanonical->EncryptedNewLicenseInfo.wBlobLen,
|
|
&NewLicense)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Try to open the system license store
|
|
if( LICENSE_STATUS_OK != (lsReturn = MapStoreError(LSOpenLicenseStore(&hStore, NULL, FALSE))) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Initialize the LSINDEX structure. This structure will be used to add/replace a license in the store
|
|
|
|
//To do that, first initialize version info
|
|
lsIndex.dwVersion = NewLicense.dwVersion;
|
|
|
|
//Initialize Scope info
|
|
lsIndex.cbScope = NewLicense.cbScope;
|
|
if( NULL == (lsIndex.pbScope = (LPSTR)malloc(lsIndex.cbScope)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(lsIndex.pbScope, 0x00, lsIndex.cbScope);
|
|
memcpy(lsIndex.pbScope, NewLicense.pbScope, lsIndex.cbScope);
|
|
|
|
|
|
//Initialize CompanyName info
|
|
lsIndex.cbCompany = NewLicense.cbCompanyName;
|
|
if( NULL == (lsIndex.pbCompany = (LPSTR)malloc(lsIndex.cbCompany)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(lsIndex.pbCompany, 0x00, lsIndex.cbCompany);
|
|
memcpy(lsIndex.pbCompany, NewLicense.pbCompanyName, lsIndex.cbCompany);
|
|
|
|
|
|
//Initialize ProductID info
|
|
lsIndex.cbProductID = NewLicense.cbProductID;
|
|
if( NULL == (lsIndex.pbProductID = (LPSTR)malloc(lsIndex.cbProductID)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(lsIndex.pbProductID, 0x00, lsIndex.cbProductID);
|
|
memcpy(lsIndex.pbProductID, NewLicense.pbProductID, lsIndex.cbProductID);
|
|
|
|
|
|
LS_LOG_RESULT(lsReturn);
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = LSAddLicenseToStore(hStore,
|
|
LS_REPLACE_LICENSE_OK,
|
|
&lsIndex,
|
|
NewLicense.pbLicenseInfo,
|
|
NewLicense.cbLicenseInfo
|
|
)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
//Update state info and inform that the License Verification is over and the client can carry on
|
|
//with further connection!
|
|
pContext->dwState = LICENSE_CLIENT_STATE_DONE;
|
|
|
|
memset(pContext->rgbMACData, 0x00, LICENSE_MAC_DATA);
|
|
|
|
//Reset the last send message to 0;
|
|
if(pContext->pbLastMessage)
|
|
{
|
|
memset(pContext->pbLastMessage, 0x00, pContext->cbLastMessage);
|
|
free(pContext->pbLastMessage);
|
|
pContext->pbLastMessage = NULL;
|
|
}
|
|
pContext->cbLastMessage = 0;
|
|
|
|
lsReturn = LICENSE_STATUS_OK;
|
|
|
|
CommonReturn:
|
|
|
|
if( hStore )
|
|
{
|
|
LSCloseLicenseStore( hStore );
|
|
}
|
|
|
|
if(NewLicense.pbScope)
|
|
{
|
|
free(NewLicense.pbScope);
|
|
NewLicense.pbScope = NULL;
|
|
}
|
|
|
|
if(NewLicense.pbCompanyName)
|
|
{
|
|
free(NewLicense.pbCompanyName);
|
|
NewLicense.pbCompanyName = NULL;
|
|
}
|
|
|
|
if(NewLicense.pbProductID)
|
|
{
|
|
free(NewLicense.pbProductID);
|
|
NewLicense.pbProductID = NULL;
|
|
}
|
|
|
|
if(NewLicense.pbLicenseInfo)
|
|
{
|
|
free(NewLicense.pbLicenseInfo);
|
|
NewLicense.pbLicenseInfo = NULL;
|
|
}
|
|
|
|
if(lsIndex.pbScope)
|
|
{
|
|
free(lsIndex.pbScope);
|
|
lsIndex.pbScope = NULL;
|
|
}
|
|
|
|
if(lsIndex.pbCompany)
|
|
{
|
|
free(lsIndex.pbCompany);
|
|
lsIndex.pbCompany = NULL;
|
|
}
|
|
if(lsIndex.pbProductID)
|
|
{
|
|
free(lsIndex.pbProductID);
|
|
lsIndex.pbProductID = NULL;
|
|
}
|
|
|
|
if(bbData.pBlob)
|
|
{
|
|
free(bbData.pBlob);
|
|
bbData.pBlob = NULL;
|
|
}
|
|
|
|
return lsReturn;
|
|
|
|
ErrorReturn:
|
|
goto CommonReturn;
|
|
}
|
|
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
ClientConstructLicenseInfo(
|
|
PLicense_Client_Context pContext,
|
|
BYTE FAR * pbInput,
|
|
DWORD cbInput,
|
|
BYTE FAR * pbOutput,
|
|
DWORD FAR * pcbOutput,
|
|
BOOL fExtendedError
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
Hydra_Client_License_Info Canonical;
|
|
HWID hwid;
|
|
Binary_Blob bbPreMasterSecret;
|
|
DWORD dwSize = 0;
|
|
DWORD dwState = 0;
|
|
PBYTE pbServerPubKey;
|
|
DWORD cbServerPubKey;
|
|
|
|
LS_BEGIN(TEXT("ClientContstructLicenseInfo"));
|
|
|
|
if(NULL == pContext || NULL == pcbOutput)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Construct the messages
|
|
bbPreMasterSecret.wBlobType = BB_RANDOM_BLOB;
|
|
bbPreMasterSecret.wBlobLen = LICENSE_PRE_MASTER_SECRET;
|
|
if( NULL == (bbPreMasterSecret.pBlob = (BYTE FAR *)malloc(LICENSE_PRE_MASTER_SECRET)) )
|
|
{
|
|
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memcpy(bbPreMasterSecret.pBlob, pContext->pCryptParam->rgbPreMasterSecret, LICENSE_PRE_MASTER_SECRET);
|
|
memset(&Canonical, 0x00, sizeof(Hydra_Client_License_Info));
|
|
|
|
//RSA is hardcoded for the time being
|
|
Canonical.dwPrefKeyExchangeAlg = pContext->pCryptParam->dwKeyExchAlg;
|
|
|
|
#ifdef OS_WINCE
|
|
Canonical.dwPlatformID = CLIENT_OS_ID_OTHER | CLIENT_IMAGE_ID_MICROSOFT;
|
|
#else // WinNT or Win9x
|
|
{
|
|
DWORD dwVersion = GetVersion();
|
|
|
|
if (dwVersion & 0x80000000) {
|
|
// Win95
|
|
Canonical.dwPlatformID = CLIENT_OS_ID_OTHER | CLIENT_IMAGE_ID_MICROSOFT;
|
|
} else {
|
|
|
|
OSVERSIONINFOEX ovix;
|
|
BOOL b;
|
|
ovix.dwOSVersionInfoSize = sizeof(ovix);
|
|
b = GetVersionEx((LPOSVERSIONINFO) &ovix);
|
|
if(b && ((ovix.wSuiteMask & VER_SUITE_EMBEDDEDNT) || (ovix.wSuiteMask & VER_SUITE_PERSONAL)))
|
|
{
|
|
Canonical.dwPlatformID = CLIENT_OS_ID_WINNT_40 | CLIENT_IMAGE_ID_MICROSOFT;
|
|
}
|
|
else
|
|
{
|
|
|
|
// WinNT
|
|
Canonical.dwPlatformID = CLIENT_IMAGE_ID_MICROSOFT |
|
|
((((DWORD)(LOBYTE(LOWORD(dwVersion)))) - 2) << 24);
|
|
|
|
Canonical.dwPlatformID |= (DWORD)(HIBYTE(LOWORD(dwVersion)));
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//ClientRandom
|
|
memcpy(Canonical.ClientRandom, pContext->pCryptParam->rgbClientRandom, LICENSE_RANDOM);
|
|
|
|
if( pContext->pServerCert )
|
|
{
|
|
//
|
|
// This public key is used for pre-Hydra 5.0 servers that are using proprietory
|
|
// server certificates.
|
|
//
|
|
|
|
pbServerPubKey = pContext->pServerCert->PublicKeyData.pBlob;
|
|
cbServerPubKey = pContext->pServerCert->PublicKeyData.wBlobLen;
|
|
}
|
|
else
|
|
{
|
|
pbServerPubKey = pContext->pbServerPubKey;
|
|
cbServerPubKey = pContext->cbServerPubKey;
|
|
}
|
|
|
|
//We have to switch here depending on the key exchange algorithm to be used -Shubho
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEnvelopeData(pbServerPubKey,
|
|
cbServerPubKey,
|
|
bbPreMasterSecret.pBlob,
|
|
bbPreMasterSecret.wBlobLen,
|
|
NULL,
|
|
&dwSize)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if( NULL == (Canonical.EncryptedPreMasterSecret.pBlob = (BYTE FAR *)malloc(dwSize)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(Canonical.EncryptedPreMasterSecret.pBlob, 0x00, dwSize);
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEnvelopeData(pbServerPubKey,
|
|
cbServerPubKey,
|
|
bbPreMasterSecret.pBlob,
|
|
bbPreMasterSecret.wBlobLen,
|
|
Canonical.EncryptedPreMasterSecret.pBlob,
|
|
&dwSize)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
Canonical.EncryptedPreMasterSecret.wBlobLen = (WORD)dwSize;
|
|
|
|
//Fill up LicenseInfo buffer
|
|
Canonical.LicenseInfo.wBlobType = BB_DATA_BLOB;
|
|
Canonical.LicenseInfo.wBlobLen = (WORD)cbInput;
|
|
if( NULL == (Canonical.LicenseInfo.pBlob = (BYTE FAR *)malloc(Canonical.LicenseInfo.wBlobLen)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(Canonical.LicenseInfo.pBlob, 0x00, Canonical.LicenseInfo.wBlobLen);
|
|
memcpy(Canonical.LicenseInfo.pBlob, pbInput, Canonical.LicenseInfo.wBlobLen);
|
|
|
|
|
|
//Generate HWID and put the data in a binary_blob to encrypt
|
|
memset(&hwid, 0x00, sizeof(HWID));
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = GenerateClientHWID(&hwid)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
Canonical.EncryptedHWID.wBlobType = BB_DATA_BLOB;
|
|
Canonical.EncryptedHWID.wBlobLen = sizeof(HWID);
|
|
if( NULL == (Canonical.EncryptedHWID.pBlob = (BYTE FAR *)malloc(Canonical.EncryptedHWID.wBlobLen)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(Canonical.EncryptedHWID.pBlob, 0x00, Canonical.EncryptedHWID.wBlobLen);
|
|
memcpy(Canonical.EncryptedHWID.pBlob, &hwid, Canonical.EncryptedHWID.wBlobLen);
|
|
|
|
dwState = pContext->pCryptParam->dwCryptState;
|
|
//Generate the session key and MACsalt
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseBuildMasterSecret(pContext->pCryptParam)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseMakeSessionKeys(pContext->pCryptParam, 0)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Encrypt the HWID with generated session key
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEncryptSessionData(pContext->pCryptParam,
|
|
Canonical.EncryptedHWID.pBlob,
|
|
(DWORD)Canonical.EncryptedHWID.wBlobLen)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
//Generate the MAC with original HWID
|
|
LicenseGenerateMAC(pContext->pCryptParam, ( BYTE FAR * )&hwid, sizeof(hwid), Canonical.MACData);
|
|
|
|
//Now everything is ready, so pack the data
|
|
if( LICENSE_STATUS_OK != (lsReturn = PackHydraClientLicenseInfo(&Canonical, fExtendedError, pbOutput, pcbOutput)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Set the MACData in the CryptSystem MAC buffer.
|
|
memcpy(pContext->rgbMACData, Canonical.MACData, LICENSE_MAC_DATA);
|
|
|
|
//Set the state of the context to LICENSE_CLIENT_STATE_LICENSE_RESPONSE
|
|
//if any output data is written. i.e. pbOutput is not null. Also revert back
|
|
//the crypparam state as this will also be called twice and we change the state
|
|
//only when we have written something in the output!!!!! - bad!!!!!
|
|
if(pbOutput)
|
|
{
|
|
pContext->dwState = LICENSE_CLIENT_STATE_LICENSE_RESPONSE;
|
|
}
|
|
|
|
else //Restore earlier CryptSystem States
|
|
{
|
|
pContext->pCryptParam->dwCryptState = dwState;
|
|
memcpy(pContext->pCryptParam->rgbPreMasterSecret, bbPreMasterSecret.pBlob, LICENSE_PRE_MASTER_SECRET);
|
|
memset(pContext->pCryptParam->rgbSessionKey, 0x00, LICENSE_SESSION_KEY);
|
|
memset(pContext->pCryptParam->rgbMACSaltKey, 0x00, LICENSE_MAC_WRITE_KEY);
|
|
}
|
|
|
|
//Copy the whole message to the context
|
|
pContext->cbLastMessage = *pcbOutput;
|
|
if(pbOutput)
|
|
{
|
|
if( pContext->pbLastMessage )
|
|
{
|
|
free( pContext->pbLastMessage );
|
|
}
|
|
|
|
if( NULL == (pContext->pbLastMessage = (BYTE FAR *)malloc(pContext->cbLastMessage)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
goto ErrorReturn;
|
|
}
|
|
memset(pContext->pbLastMessage, 0x00, pContext->cbLastMessage);
|
|
memcpy(pContext->pbLastMessage, pbOutput, pContext->cbLastMessage);
|
|
}
|
|
|
|
lsReturn = LICENSE_STATUS_CONTINUE;
|
|
LS_LOG_RESULT(lsReturn);
|
|
CommonReturn:
|
|
|
|
if(Canonical.EncryptedPreMasterSecret.pBlob)
|
|
{
|
|
free(Canonical.EncryptedPreMasterSecret.pBlob);
|
|
Canonical.EncryptedPreMasterSecret.pBlob = NULL;
|
|
}
|
|
|
|
if(Canonical.LicenseInfo.pBlob)
|
|
{
|
|
free(Canonical.LicenseInfo.pBlob);
|
|
Canonical.LicenseInfo.pBlob = NULL;
|
|
}
|
|
|
|
if(Canonical.EncryptedHWID.pBlob)
|
|
{
|
|
free(Canonical.EncryptedHWID.pBlob);
|
|
Canonical.EncryptedHWID.pBlob = NULL;
|
|
}
|
|
|
|
if(bbPreMasterSecret.pBlob)
|
|
{
|
|
free(bbPreMasterSecret.pBlob);
|
|
bbPreMasterSecret.pBlob = NULL;
|
|
}
|
|
|
|
return lsReturn;
|
|
// LS_RETURN(lsReturn);
|
|
ErrorReturn:
|
|
*pcbOutput = 0;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
ClientConstructNewLicenseRequest(
|
|
PLicense_Client_Context pContext,
|
|
BYTE FAR * pbOutput,
|
|
DWORD FAR * pcbOutput,
|
|
BOOL fExtendedError
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
Hydra_Client_New_License_Request Request;
|
|
Binary_Blob bbPreMasterSecret;
|
|
DWORD dwSize = 0;
|
|
DWORD dwState = 0;
|
|
|
|
#ifdef OS_WINCE
|
|
|
|
#define LS_MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
BYTE szUserName[LS_MAX((UNLEN + 1),HWID_STR_LEN)];
|
|
DWORD cbUserName = sizeof(szUserName);
|
|
BYTE szMachineName[LS_MAX(MAX_COMPUTERNAME_LENGTH + 1,HWID_STR_LEN)];
|
|
DWORD cbMachineName = sizeof(szMachineName);
|
|
|
|
#else
|
|
|
|
BYTE szUserName[(UNLEN + 1) * sizeof(TCHAR)];
|
|
DWORD cbUserName = UNLEN + 1;
|
|
BYTE szMachineName[(MAX_COMPUTERNAME_LENGTH + 1) * sizeof(TCHAR)];
|
|
DWORD cbMachineName = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(TCHAR);
|
|
|
|
#endif
|
|
|
|
PBYTE pbServerPubKey;
|
|
DWORD cbServerPubKey;
|
|
|
|
LS_BEGIN(TEXT("ClientConstructNewLicenseRequest"));
|
|
|
|
if(NULL == pContext)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(szUserName,0,sizeof(szUserName));
|
|
memset(szMachineName,0,sizeof(szMachineName));
|
|
|
|
|
|
dwState = pContext->pCryptParam->dwCryptState;
|
|
|
|
bbPreMasterSecret.wBlobType = BB_RANDOM_BLOB;
|
|
bbPreMasterSecret.wBlobLen = LICENSE_PRE_MASTER_SECRET;
|
|
if( NULL == (bbPreMasterSecret.pBlob = (BYTE FAR *)malloc(LICENSE_PRE_MASTER_SECRET)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memcpy(bbPreMasterSecret.pBlob, pContext->pCryptParam->rgbPreMasterSecret, LICENSE_PRE_MASTER_SECRET);
|
|
|
|
//Initialize the message
|
|
memset(&Request, 0x00, sizeof(Hydra_Client_New_License_Request));
|
|
|
|
//RSA is hardcoded for the time being
|
|
Request.dwPrefKeyExchangeAlg = pContext->pCryptParam->dwKeyExchAlg;
|
|
|
|
//PlatformID
|
|
#ifdef OS_WINCE
|
|
Request.dwPlatformID = CLIENT_OS_ID_OTHER | CLIENT_IMAGE_ID_MICROSOFT;
|
|
#else // WinNT or Win9x
|
|
{
|
|
DWORD dwVersion = GetVersion();
|
|
|
|
if (dwVersion & 0x80000000) {
|
|
// Win95
|
|
Request.dwPlatformID = CLIENT_OS_ID_OTHER | CLIENT_IMAGE_ID_MICROSOFT;
|
|
} else {
|
|
|
|
OSVERSIONINFOEX ovix;
|
|
BOOL b;
|
|
ovix.dwOSVersionInfoSize = sizeof(ovix);
|
|
b = GetVersionEx((LPOSVERSIONINFO) &ovix);
|
|
if(b && ((ovix.wSuiteMask & VER_SUITE_EMBEDDEDNT) || (ovix.wSuiteMask & VER_SUITE_PERSONAL)))
|
|
{
|
|
Request.dwPlatformID = CLIENT_OS_ID_WINNT_40 | CLIENT_IMAGE_ID_MICROSOFT;
|
|
}
|
|
else
|
|
{
|
|
|
|
// WinNT
|
|
Request.dwPlatformID = CLIENT_IMAGE_ID_MICROSOFT |
|
|
((((DWORD)(LOBYTE(LOWORD(dwVersion)))) - 2) << 24);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//Copy ClientRandom
|
|
memcpy(Request.ClientRandom, pContext->pCryptParam->rgbClientRandom, LICENSE_RANDOM);
|
|
|
|
//Encrypt the Premastersecret using Server's Public key
|
|
//We have to switch here depending on the key exchange algorithm to be used -Shubho
|
|
|
|
if( pContext->pServerCert )
|
|
{
|
|
//
|
|
// This public key is used for pre-Hydra 5.0 servers that are using proprietory
|
|
// server certificates.
|
|
//
|
|
|
|
pbServerPubKey = pContext->pServerCert->PublicKeyData.pBlob;
|
|
cbServerPubKey = pContext->pServerCert->PublicKeyData.wBlobLen;
|
|
}
|
|
else
|
|
{
|
|
pbServerPubKey = pContext->pbServerPubKey;
|
|
cbServerPubKey = pContext->cbServerPubKey;
|
|
}
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEnvelopeData(pbServerPubKey,
|
|
cbServerPubKey,
|
|
bbPreMasterSecret.pBlob,
|
|
bbPreMasterSecret.wBlobLen,
|
|
NULL,
|
|
&dwSize)) )
|
|
{
|
|
#if DBG
|
|
OutputDebugString(_T("LicenseEnvelopeData failed"));
|
|
LS_LOG_RESULT(lsReturn);
|
|
#endif
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if( NULL == (Request.EncryptedPreMasterSecret.pBlob = (BYTE FAR *)malloc(dwSize)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(Request.EncryptedPreMasterSecret.pBlob, 0x00, dwSize);
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseEnvelopeData(pbServerPubKey,
|
|
cbServerPubKey,
|
|
bbPreMasterSecret.pBlob,
|
|
bbPreMasterSecret.wBlobLen,
|
|
Request.EncryptedPreMasterSecret.pBlob,
|
|
&dwSize)) )
|
|
{
|
|
#if DBG
|
|
OutputDebugString(_T("LicenseEnvelopeData failed"));
|
|
LS_LOG_RESULT(lsReturn);
|
|
#endif
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
Request.EncryptedPreMasterSecret.wBlobLen = (WORD)dwSize;
|
|
|
|
//
|
|
// initialize the user name binary blob
|
|
//
|
|
#if !defined(OS_WINCE)
|
|
GetUserName( (LPTSTR)szUserName, &cbUserName );
|
|
#elif defined(OS_WINCE)
|
|
GetUserName( (LPSTR)szUserName, &cbUserName );
|
|
#endif //OS_WINCE
|
|
|
|
Request.ClientUserName.wBlobType = BB_CLIENT_USER_NAME_BLOB;
|
|
Request.ClientUserName.wBlobLen = ( WORD )cbUserName;
|
|
Request.ClientUserName.pBlob = szUserName;
|
|
|
|
//
|
|
// initialize the machine name binary blob
|
|
//
|
|
|
|
#if defined(OS_WINCE)
|
|
GetComputerName( (LPSTR)szMachineName, &cbMachineName );
|
|
#else
|
|
GetComputerName( (LPTSTR)szMachineName, &cbMachineName );
|
|
#endif
|
|
|
|
Request.ClientMachineName.wBlobType = BB_CLIENT_MACHINE_NAME_BLOB;
|
|
Request.ClientMachineName.wBlobLen = ( WORD )cbMachineName + 1;
|
|
Request.ClientMachineName.pBlob = szMachineName;
|
|
|
|
//New License Request is ready. Now pack the data,
|
|
if( LICENSE_STATUS_OK != (lsReturn = PackHydraClientNewLicenseRequest(&Request,
|
|
fExtendedError,
|
|
pbOutput,
|
|
pcbOutput)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Anyway Generate the session key and MACsalt for future use
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseBuildMasterSecret(pContext->pCryptParam)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = LicenseMakeSessionKeys(pContext->pCryptParam, 0)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Set the MACData in the CryptSystem MAC buffer.
|
|
memset(pContext->rgbMACData, 0x00, LICENSE_MAC_DATA);
|
|
|
|
//Set the state of the context to LICENSE_CLIENT_STATE_NEW_LICENSE_REQUEST
|
|
//if something is written on the output. i.e. pbOutput is not NULL
|
|
if(pbOutput)
|
|
{
|
|
pContext->dwState = LICENSE_CLIENT_STATE_LICENSE_RESPONSE;
|
|
}
|
|
|
|
else //Restore earlier CryptSystem States
|
|
{
|
|
pContext->pCryptParam->dwCryptState = dwState;
|
|
memcpy(pContext->pCryptParam->rgbPreMasterSecret, bbPreMasterSecret.pBlob, LICENSE_PRE_MASTER_SECRET);
|
|
memset(pContext->pCryptParam->rgbSessionKey, 0x00, LICENSE_SESSION_KEY);
|
|
memset(pContext->pCryptParam->rgbMACSaltKey, 0x00, LICENSE_MAC_WRITE_KEY);
|
|
}
|
|
|
|
//Copy the whole message to the context
|
|
pContext->cbLastMessage = *pcbOutput;
|
|
if(pbOutput)
|
|
{
|
|
if( pContext->pbLastMessage )
|
|
{
|
|
free( pContext->pbLastMessage );
|
|
}
|
|
|
|
if( NULL == (pContext->pbLastMessage = (BYTE FAR *)malloc(pContext->cbLastMessage)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(pContext->pbLastMessage, 0x00, pContext->cbLastMessage);
|
|
memcpy(pContext->pbLastMessage, pbOutput, pContext->cbLastMessage);
|
|
}
|
|
|
|
lsReturn = LICENSE_STATUS_CONTINUE;
|
|
LS_LOG_RESULT(lsReturn);
|
|
CommonReturn:
|
|
|
|
if(bbPreMasterSecret.pBlob)
|
|
{
|
|
free(bbPreMasterSecret.pBlob);
|
|
bbPreMasterSecret.pBlob = NULL;
|
|
}
|
|
|
|
if( Request.EncryptedPreMasterSecret.pBlob )
|
|
{
|
|
free( Request.EncryptedPreMasterSecret.pBlob );
|
|
}
|
|
|
|
return lsReturn;
|
|
//LS_RETURN(lsReturn);
|
|
ErrorReturn:
|
|
*pcbOutput = 0;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
ClientConstructErrorAlert(
|
|
PLicense_Client_Context pContext,
|
|
DWORD dwErrorCode,
|
|
DWORD dwStateTransition,
|
|
BYTE FAR * pbErrorInfo,
|
|
DWORD cbErrorInfo,
|
|
BYTE FAR * pbOutput,
|
|
DWORD FAR * pcbOutput,
|
|
BOOL fExtendedError
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
License_Error_Message Error;
|
|
|
|
LS_BEGIN(TEXT("ClientConstructErrorAlert\n"));
|
|
|
|
if(NULL == pContext)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
memset(&Error, 0x00, sizeof(License_Error_Message));
|
|
Error.dwErrorCode = dwErrorCode;
|
|
Error.dwStateTransition = dwStateTransition;
|
|
Error.bbErrorInfo.wBlobType = BB_ERROR_BLOB;
|
|
Error.bbErrorInfo.wBlobLen = (WORD)cbErrorInfo;
|
|
if(Error.bbErrorInfo.wBlobLen>0)
|
|
{
|
|
if( NULL == (Error.bbErrorInfo.pBlob = (BYTE FAR *)malloc(Error.bbErrorInfo.wBlobLen)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(Error.bbErrorInfo.pBlob, 0x00, Error.bbErrorInfo.wBlobLen);
|
|
memcpy(Error.bbErrorInfo.pBlob, pbErrorInfo, Error.bbErrorInfo.wBlobLen);
|
|
}
|
|
else
|
|
Error.bbErrorInfo.pBlob = NULL;
|
|
|
|
if( LICENSE_STATUS_OK != (lsReturn = PackLicenseErrorMessage(&Error,
|
|
fExtendedError,
|
|
pbOutput,
|
|
pcbOutput)) )
|
|
{
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//Set the MACData in the CryptSystem MAC buffer.
|
|
memset(pContext->rgbMACData, 0x00, LICENSE_MAC_DATA);
|
|
|
|
//Set the state of the context to LICENSE_CLIENT_STATE_ABORT;
|
|
switch(dwStateTransition)
|
|
{
|
|
case ST_TOTAL_ABORT:
|
|
pContext->dwState = LICENSE_CLIENT_STATE_ABORT;
|
|
lsReturn = LICENSE_STATUS_CLIENT_ABORT;
|
|
pContext->cbLastMessage = 0;
|
|
break;
|
|
case ST_NO_TRANSITION:
|
|
lsReturn = LICENSE_STATUS_CONTINUE;
|
|
pContext->cbLastMessage = *pcbOutput;
|
|
if(pbOutput)
|
|
{
|
|
if( pContext->pbLastMessage )
|
|
{
|
|
free( pContext->pbLastMessage );
|
|
}
|
|
|
|
if( NULL == (pContext->pbLastMessage = (BYTE FAR *)malloc(pContext->cbLastMessage)) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
memset(pContext->pbLastMessage, 0x00, pContext->cbLastMessage);
|
|
memcpy(pContext->pbLastMessage, pbOutput, pContext->cbLastMessage);
|
|
}
|
|
break;
|
|
case ST_RESET_PHASE_TO_START:
|
|
lsReturn = LICENSE_STATUS_CONTINUE;
|
|
if( (pContext->dwState == LICENSE_CLIENT_STATE_LICENSE_RESPONSE) ||
|
|
(pContext->dwState == LICENSE_CLIENT_STATE_NEW_LICENSE_REQUEST) )
|
|
{
|
|
pContext->dwState = LICENSE_CLIENT_STATE_WAIT_SERVER_HELLO;
|
|
}
|
|
else if(pContext->dwState == LICENSE_CLIENT_STATE_PLATFORM_CHALLENGE_RESPONSE)
|
|
{
|
|
pContext->dwState = LICENSE_CLIENT_STATE_NEW_LICENSE_REQUEST;
|
|
}
|
|
break;
|
|
case ST_RESEND_LAST_MESSAGE:
|
|
lsReturn = LICENSE_STATUS_CONTINUE;
|
|
break;
|
|
}
|
|
|
|
LS_LOG_RESULT(lsReturn);
|
|
CommonReturn:
|
|
|
|
if(Error.bbErrorInfo.pBlob)
|
|
{
|
|
free(Error.bbErrorInfo.pBlob);
|
|
Error.bbErrorInfo.pBlob = NULL;
|
|
}
|
|
return lsReturn;
|
|
//LS_RETURN(lsReturn);
|
|
ErrorReturn:
|
|
*pcbOutput = 0;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
|
|
LICENSE_STATUS
|
|
CALL_TYPE
|
|
ClientGenerateChallengeResponse(
|
|
PLicense_Client_Context pContext,
|
|
PBinary_Blob pChallengeData,
|
|
PBinary_Blob pResponseData
|
|
)
|
|
{
|
|
LICENSE_STATUS lsReturn = LICENSE_STATUS_OK;
|
|
PPlatformChallengeResponseData pbChallengeResponse = NULL;
|
|
WORD cbChallengeResponse;
|
|
|
|
|
|
LS_BEGIN(TEXT("ClientGenerateChallengeResponse"));
|
|
|
|
//For the time being we will send back the same data. But we have to finalize on the challenge
|
|
//response generation algorithm as soon as possible - Shubho
|
|
if( (pContext == NULL) || (pChallengeData == NULL) || (pResponseData == NULL) )
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
pResponseData->wBlobType = BB_DATA_BLOB;
|
|
|
|
//
|
|
// Determine how much memory we need to allocate, PlatformChallenge* is a variable length
|
|
// structure.
|
|
//
|
|
cbChallengeResponse = (WORD)OFFSET_OF(PlatformChallengeResponseData, pbChallenge) + pChallengeData->wBlobLen;
|
|
|
|
ASSERT(cbChallengeResponse <= PLATFORM_CHALLENGE_LENGTH);
|
|
if(cbChallengeResponse > PLATFORM_CHALLENGE_LENGTH)
|
|
{
|
|
lsReturn = LICENSE_STATUS_INVALID_INPUT;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
pbChallengeResponse = (PPlatformChallengeResponseData)malloc(cbChallengeResponse);
|
|
if( NULL == pbChallengeResponse )
|
|
{
|
|
// can't allocate memory
|
|
lsReturn = LICENSE_STATUS_OUT_OF_MEMORY;
|
|
LS_LOG_RESULT(lsReturn);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Setup challenge response data,
|
|
//
|
|
|
|
pbChallengeResponse->wVersion = CURRENT_PLATFORMCHALLENGE_VERSION;
|
|
|
|
|
|
#ifdef OS_WINCE
|
|
|
|
pbChallengeResponse->wClientType = WINCE_PLATFORMCHALLENGE_TYPE;
|
|
pbChallengeResponse->wLicenseDetailLevel = LICENSE_DETAIL_DETAIL;
|
|
|
|
#else
|
|
|
|
//
|
|
// We only need one Win32 type since we already have dwPlatformID to differentiate Win98/NT
|
|
// Note, we set license detail level in #define just in case platform can't handle amount
|
|
// of data set back by license server
|
|
//
|
|
pbChallengeResponse->wClientType = WIN32_PLATFORMCHALLENGE_TYPE;
|
|
pbChallengeResponse->wLicenseDetailLevel = LICENSE_DETAIL_DETAIL;
|
|
|
|
#endif
|
|
|
|
if( (pChallengeData->pBlob != NULL) && (pChallengeData->wBlobLen >0) )
|
|
{
|
|
pbChallengeResponse->cbChallenge = pChallengeData->wBlobLen;
|
|
memcpy(
|
|
(PBYTE)pbChallengeResponse + OFFSET_OF(PlatformChallengeResponseData, pbChallenge),
|
|
pChallengeData->pBlob,
|
|
pChallengeData->wBlobLen
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// server didn't send us any challenge data.
|
|
pbChallengeResponse->cbChallenge = 0;
|
|
}
|
|
|
|
pResponseData->wBlobLen = cbChallengeResponse;
|
|
pResponseData->pBlob = (BYTE FAR *)pbChallengeResponse;
|
|
|
|
lsReturn = LICENSE_STATUS_OK;
|
|
LS_LOG_RESULT(lsReturn);
|
|
|
|
CommonReturn:
|
|
//LS_RETURN(lsReturn);
|
|
return lsReturn;
|
|
ErrorReturn:
|
|
goto CommonReturn;
|
|
}
|
|
|
|
static BOOL GeneratePseudoLicense(
|
|
DWORD FAR * pcbNewLicense,
|
|
LPBYTE FAR *ppNewLicense)
|
|
{
|
|
TCHAR g_LicenseString[] = TEXT("Licensed To Kill");
|
|
|
|
#define REPEAT_LICENSE_STRING 15
|
|
#define LICENSE_STRING_LEN sizeof(TCHAR) * lstrlen(g_LicenseString)
|
|
|
|
#define LICENSE_SIZE ( LICENSE_STRING_LEN * REPEAT_LICENSE_STRING ) + 1 * sizeof(TCHAR)
|
|
|
|
UINT i;
|
|
BYTE FAR *pbLicenseData = NULL;
|
|
DWORD cbLicenseData = LICENSE_SIZE;
|
|
|
|
if( NULL == ( *ppNewLicense = malloc(cbLicenseData) ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memset(*ppNewLicense, 0x00, cbLicenseData);
|
|
//
|
|
// fill the memory with this license string
|
|
//
|
|
pbLicenseData = *ppNewLicense;
|
|
for( i = 0; i < REPEAT_LICENSE_STRING; i++ )
|
|
{
|
|
memcpy( pbLicenseData, g_LicenseString, LICENSE_STRING_LEN );
|
|
pbLicenseData += LICENSE_STRING_LEN;
|
|
}
|
|
|
|
*pcbNewLicense = cbLicenseData;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeProprietaryCertificate(
|
|
PHydra_Server_Cert * ppCertificate )
|
|
{
|
|
if( NULL == *ppCertificate )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( ( *ppCertificate )->PublicKeyData.pBlob )
|
|
{
|
|
free( ( *ppCertificate )->PublicKeyData.pBlob );
|
|
}
|
|
|
|
if( ( *ppCertificate )->SignatureBlob.pBlob )
|
|
{
|
|
free( ( *ppCertificate )->SignatureBlob.pBlob );
|
|
}
|
|
|
|
free( *ppCertificate );
|
|
|
|
*ppCertificate = NULL;
|
|
}
|