|
|
/*++
File name:
csp.c
Description: Contains routines to support cryptographic routines for termserv
Copyright:
Microsoft Confidential Copyright (c) Microsoft Corporation 1991-1998 All rights reserved
History:
Frederick Chong( FredCh ) 07/29/98 Added functions to install X509 certificate. --*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntlsa.h>
#include <windows.h>
#include <winbase.h>
#include <winerror.h>
#include <tchar.h>
#include <stdio.h>
#include "license.h"
#include "cryptkey.h"
#include "rng.h"
#include "lscsp.h"
#include "tlsapip.h"
#include "certutil.h"
#include "hydrakey.h"
#include <md5.h>
#include <sha.h>
#include <rsa.h>
#include <secdbg.h>
#include "global.h"
#ifdef OS_WIN16
#include <string.h>
#endif // OS_WIN16
#include "licecert.h"
#define LS_DISCOVERY_TIMEOUT (1*1000)
//-----------------------------------------------------------------------------
//
// Internal Functions
//
//-----------------------------------------------------------------------------
NTSTATUS OpenPolicy( LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle );
void InitLsaString( PLSA_UNICODE_STRING LsaString, LPWSTR String );
LICENSE_STATUS GenerateRsaKeyPair( LPBYTE * ppbPublicKey, LPDWORD pcbPublicKey, LPBYTE * ppbPrivateKey, LPDWORD pcbPrivateKey, DWORD dwKeyLen );
LICENSE_STATUS Bsafe2CapiPubKey( PCERT_PUBLIC_KEY_INFO pCapiPubKeyInfo, LPBYTE pbBsafePubKey, DWORD cbBsafePubKey );
VOID FreeCapiPubKey( PCERT_PUBLIC_KEY_INFO pCapiPubKeyInfo );
LICENSE_STATUS RequestCertificate( TLS_HANDLE hServer, PCERT_PUBLIC_KEY_INFO pPubKeyInfo, LPBYTE * ppbCertificate, LPDWORD pcbCertificate, HWID * pHwid );
LICENSE_STATUS GetSubjectRdn( LPTSTR * ppSubjectRdn );
LICENSE_STATUS GenerateMachineHWID( PHWID pHwid );
LICENSE_STATUS ReloadCSPCertificateAndData();
LICENSE_STATUS CreateProprietaryKeyAndCert( PBYTE *ppbPrivateKey, DWORD *pcbPrivateKey, PBYTE *ppbServerCert, DWORD *pcbServerCert);
BOOL IsSystemService();
/*++
Function:
LsCsp_ValidateServerCert
Routine Description:
This function validate the server public key.
Arguments:
pSserverCert - pointer to a server certificate.
Return Value:
TRUE - if the server public key is valid. FALSE - otherwise.
--*/
BOOL LsCsp_ValidateServerCert( PHydra_Server_Cert pServerCert ) { BOOL bResult = TRUE; DWORD dwLen; LPBYTE pbSignature; MD5_CTX HashState; BYTE SignHash[0x48]; DWORD buff[64]; LPBYTE pbScan;
//
// pack the certificate data into a byte blob excluding the signature info.
//
dwLen = 3 * sizeof(DWORD) + 2 * sizeof(WORD) + pServerCert->PublicKeyData.wBlobLen;
//
// allocated space for the binary blob.
//
if (dwLen < sizeof(buff)) {
pbSignature = (PBYTE)buff;
} else { pbSignature = LocalAlloc( LPTR, (UINT)dwLen ); if( pbSignature == NULL ) { #if DBG
DbgPrint("LSCSP: LsCsp_ValidateServerCert buffer alloc failed.\n"); #endif
bResult = FALSE; goto vsc_done; } }
pbScan = pbSignature;
memcpy( pbScan, &pServerCert->dwVersion, sizeof(DWORD)); pbScan += sizeof(DWORD);
memcpy( pbScan, &pServerCert->dwSigAlgID, sizeof(DWORD)); pbScan += sizeof(DWORD);
memcpy( pbScan, &pServerCert->dwKeyAlgID, sizeof(DWORD)); pbScan += sizeof(DWORD);
memcpy( pbScan, &pServerCert->PublicKeyData.wBlobType, sizeof(WORD)); pbScan += sizeof(WORD);
memcpy( pbScan, &pServerCert->PublicKeyData.wBlobLen, sizeof(WORD)); pbScan += sizeof(WORD);
memcpy( pbScan, pServerCert->PublicKeyData.pBlob, pServerCert->PublicKeyData.wBlobLen);
//
// generate the hash on the data.
//
MD5Init( &HashState ); MD5Update( &HashState, pbSignature, dwLen ); MD5Final( &HashState );
//
// free the signature blob, we don't need it anymore.
//
if (pbSignature != (LPBYTE)buff) { LocalFree( pbSignature ); }
//
// decrypt the signature.
//
memset(SignHash, 0x00, 0x48); BSafeEncPublic( csp_pRootPublicKey, pServerCert->SignatureBlob.pBlob, SignHash);
//
// compare the hash value.
//
if( memcmp( SignHash, HashState.digest, 16 )) { bResult = FALSE; } else { bResult = TRUE; }
vsc_done:
return( bResult ); }
/*++
Function:
LsCsp_UnpackServerCert
Routine Description:
This function unpacks the blob of server certicate to server certificate structure.
Arguments:
pbCert - pointer to the server public key blob.
dwCertLen - length of the above server public key.
pServerCert - pointer to a server certificate structure.
Return Value:
TRUE - if successfully unpacked. FALSE - otherwise.
--*/
BOOL LsCsp_UnpackServerCert( LPBYTE pbCert, DWORD dwCertLen, PHydra_Server_Cert pServerCert ) { LPBYTE pbScan; BOOL bResult = TRUE;
ASSERT(pbCert != NULL); ASSERT(dwCertLen < (3 * sizeof(DWORD) + 4 * sizeof(WORD))); ASSERT(pServerCert != NULL);
pbScan = pbCert;
//
// Assign dwVersion
//
pServerCert->dwVersion = *(DWORD UNALIGNED FAR *)pbScan; pbScan += sizeof(DWORD); ASSERT(pServerCert->dwVersion == 0x01);
//
// Assign dwSigAlgID
//
pServerCert->dwSigAlgID = *(DWORD UNALIGNED FAR *)pbScan; pbScan += sizeof(DWORD);
//
// Assign dwSignID
//
pServerCert->dwKeyAlgID = *(DWORD UNALIGNED FAR *)pbScan; pbScan += sizeof(DWORD);
//
// Assign PublicKeyData
//
pServerCert->PublicKeyData.wBlobType = *(WORD UNALIGNED FAR *)pbScan; pbScan += sizeof(WORD);
if( pServerCert->PublicKeyData.wBlobType != BB_RSA_KEY_BLOB ) { #if DBG
DbgPrint("LSCSP: LsCsp_UnpackServerCert PublicKey not BB_RSA_KEY_BLOB\n"); #endif
bResult = FALSE; goto usc_done; }
pServerCert->PublicKeyData.wBlobLen = *(WORD UNALIGNED FAR *)pbScan; pbScan += sizeof(WORD);
if( pServerCert->PublicKeyData.wBlobLen > 0 ) { pServerCert->PublicKeyData.pBlob = pbScan; pbScan += pServerCert->PublicKeyData.wBlobLen; } else { pServerCert->PublicKeyData.pBlob = NULL; }
//
// Assign SignatureBlob
//
pServerCert->SignatureBlob.wBlobType = *(WORD UNALIGNED *)pbScan; pbScan += sizeof(WORD);
if( pServerCert->SignatureBlob.wBlobType != BB_RSA_SIGNATURE_BLOB ) { #if DBG
DbgPrint("LSCSP: LsCsp_UnpackServerCert Signature Blob not BB_RSA_SIGNATURE_BLOB\n"); #endif
bResult = FALSE; goto usc_done; }
pServerCert->SignatureBlob.wBlobLen = *(WORD UNALIGNED FAR *)pbScan; pbScan += sizeof(WORD);
if( pServerCert->SignatureBlob.wBlobLen > 0 ) { pServerCert->SignatureBlob.pBlob = pbScan; pbScan += pServerCert->SignatureBlob.wBlobLen; } else { pServerCert->SignatureBlob.pBlob = NULL; }
usc_done:
return( bResult ); }
/*++
Function:
LsCsp_DecryptEnvelopedData
Routine Description:
Decrypt the client random that is encrypted by the server public key.
Arguments:
dwCertType - The type of certificate that is used in the encryption.
pbEnvelopedData - pointer to a buffer where the encrypted random key is passed in.
cbEnvelopedDataLen - length of the random key passed in/out.
pbData - pointer to a buffer where the decrypted data returned.
pcbDataLen - pointer a DWORD location where the length of the above buffer is passed in and the length of the decrypted data is returned.
Return Value:
TRUE - if the key is decrypted successfully. FALSE - otherwise.
--*/
BOOL LsCsp_DecryptEnvelopedData( CERT_TYPE CertType, LPBYTE pbEnvelopedData, DWORD cbEnvelopedDataLen, LPBYTE pbData, LPDWORD pcbDataLen ) { LPBSAFE_PRV_KEY pSrvPrivateKey = NULL; BOOL bResult = TRUE;
ACQUIRE_EXCLUSIVE_ACCESS(csp_hMutex);
//
// determine the correct private key to use for the decryption operation
//
if( CERT_TYPE_PROPRIETORY == CertType ) { pSrvPrivateKey = (LPBSAFE_PRV_KEY)csp_abServerPrivateKey; } else if( CERT_TYPE_X509 == CertType ) { if( csp_abX509CertPrivateKey == NULL ) { if( ReloadCSPCertificateAndData() != LICENSE_STATUS_OK ) { ASSERT( FALSE ); } }
pSrvPrivateKey = (LPBSAFE_PRV_KEY)csp_abX509CertPrivateKey; } else { bResult = FALSE; goto ded_done; } if( NULL == pSrvPrivateKey ) { bResult = FALSE; goto ded_done; }
//
// check to see the output buffer length pointer is valid.
//
if( pcbDataLen == NULL ) { bResult = FALSE; goto ded_done; }
//
// check to see the output buffer is valid and its length is sufficient.
//
if( (pbData == NULL) || (*pcbDataLen < pSrvPrivateKey->keylen) ) { *pcbDataLen = pSrvPrivateKey->keylen; bResult = FALSE; goto ded_done; }
//
// encrypted data length should be equal to server private key length.
//
if( cbEnvelopedDataLen != pSrvPrivateKey->keylen ) { *pcbDataLen = 0; bResult = FALSE; goto ded_done; }
ASSERT( pbData != NULL );
//
// init the output buffer.
//
memset( pbData, 0x0, (UINT)pSrvPrivateKey->keylen );
if( !BSafeDecPrivate( pSrvPrivateKey, pbEnvelopedData, pbData) ) { *pcbDataLen = 0; bResult = FALSE; goto ded_done; }
//
// successfully decrypted the client random.
// set the encrypted data length before returning.
//
*pcbDataLen = pSrvPrivateKey->keylen;
ded_done:
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex );
return( bResult ); }
BOOL LsCsp_EncryptEnvelopedData( LPBYTE pbData, DWORD cbDataLen, LPBYTE pbEnvelopedData, LPDWORD pcbEnvelopedDataLen ) { return FALSE; }
/*++
Function:
LsCsp_DumpBinaryData
Description:
Display the binary data in the given buffer at the debugger output screen
Arguments:
pBuffer - Buffer containing the binary data to be displayed. uLen - Length of th binary data
Return:
Nothing.
--*/
#if DBG
#ifdef DUMP
VOID LsCsp_DumpBinaryData( PBYTE pBuffer, ULONG uLen ) { UNALIGNED CHAR *p = (UNALIGNED CHAR *)pBuffer; CHAR c; DWORD dw; UINT i = 0;
DbgPrint("{\n "); while( i < uLen ) { c = *p; dw = (DWORD)(c); DbgPrint( "0x%02X, ", dw & 0xFF ); i++; p++; if ((i % 8) == 0) DbgPrint( "\n " ); } DbgPrint( "\n}\n" ); } #endif
#endif
/*++
Function:
LsCsp_GetBinaryData
Description:
Retrieve binary data from the registry
Arguments:
hKey - Handle to the registry key szValue - The registry value to read ppBuffer - Return pointer to the binary data pdwBufferLen - The length of the binary data.
Return:
A LICENSE_STATUS return code.
--*/
LICENSE_STATUS LsCsp_GetBinaryData( HKEY hKey, LPTSTR szValue, LPBYTE * ppBuffer, LPDWORD pdwBufferLen ) { LICENSE_STATUS Status = LICENSE_STATUS_OK; DWORD dwType; DWORD cbBuffer; LPBYTE lpBuffer;
ASSERT( ppBuffer != NULL ); ASSERT( pdwBufferLen != NULL ); ASSERT( szValue != NULL ); ASSERT( hKey != NULL );
*ppBuffer = NULL; cbBuffer = 0;
if ( RegQueryValueEx( hKey, szValue, 0, &dwType, (LPBYTE)NULL, &cbBuffer) != ERROR_SUCCESS || dwType != REG_BINARY || cbBuffer == 0 ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto gbd_done; } lpBuffer = (LPBYTE)LocalAlloc( LPTR, cbBuffer ); if (lpBuffer == NULL) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto gbd_done; } if ( RegQueryValueEx( hKey, szValue, 0, &dwType, (LPBYTE)lpBuffer, &cbBuffer) != ERROR_SUCCESS || dwType != REG_BINARY) { LocalFree( lpBuffer ); Status = LICENSE_STATUS_NO_CERTIFICATE; goto gbd_done; }
*ppBuffer = lpBuffer; *pdwBufferLen = cbBuffer;
gbd_done:
return( Status ); }
/*++
Function:
LsCsp_Initialize
Description:
Initialize this library.
Arguments:
Nothing.
Return:
A LICENSE_STATUS return code.
--*/
LICENSE_STATUS LsCsp_Initialize( void ) { DWORD Status = LICENSE_STATUS_OK; DWORD dwResult, dwDisp;
if( InterlockedIncrement( &csp_InitCount ) > 1 ) { //
// already initialized
//
return( LICENSE_STATUS_OK ); }
//
// Create a global mutex for sync.
//
csp_hMutex = CreateMutex( NULL, FALSE, NULL );
if(NULL == csp_hMutex) {
#if DBG
DbgPrint("LSCSP: CreateMutex() failed with error code %d\n", GetLastError()); #endif
Status = LICENSE_STATUS_OUT_OF_MEMORY; goto ErrorExit; }
//
// initialize the Hydra Server Root Public key.
//
csp_pRootPublicKey = (LPBSAFE_PUB_KEY)csp_abPublicKeyModulus; csp_pRootPublicKey->magic = RSA1; csp_pRootPublicKey->keylen = 0x48; csp_pRootPublicKey->bitlen = 0x0200; csp_pRootPublicKey->datalen = 0x3f; csp_pRootPublicKey->pubexp = 0xc0887b5b;
#if DBG
#ifdef DUMP
DbgPrint("Data0\n"); LsCsp_DumpBinaryData( (LPBYTE)csp_pRootPublicKey, 92 ); #endif
#endif
//
// Initialize the proprietory certificate with the built in certificate
//
if( !LsCsp_UseBuiltInCert() ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto ErrorExit; }
//
// Unpack and Validate the certificate
//
try { if (!LsCsp_UnpackServerCert( csp_abServerCertificate, csp_dwServerCertificateLen, &csp_hscData )) { Status = LICENSE_STATUS_INVALID_CERTIFICATE; goto ErrorExit; } if (!LsCsp_ValidateServerCert( &csp_hscData )) { Status = LICENSE_STATUS_INVALID_CERTIFICATE; } } except( EXCEPTION_EXECUTE_HANDLER ) { #if DBG
DbgPrint("LSCSP: LsCsp_Initialize bad cert data!\n"); #endif
Status = LICENSE_STATUS_INVALID_CERTIFICATE; }
Status = ReloadCSPCertificateAndData();
if (LICENSE_STATUS_NO_CERTIFICATE == Status) { //
// No X509 certificate. Not a failure, as the discovery
// thread will soon install it.
//
Status = LICENSE_STATUS_OK; } else if(LICENSE_STATUS_OUT_OF_MEMORY == Status) { //
// out of memory at initialization time,
// this is critical error
//
goto ErrorExit; }
//
// Let initalization go thru if it can retrieve
// private key from LSA, this is OK since we will try to install
// certificate again in LsCsp_InstallX509Certificate()
//
Status = LICENSE_STATUS_OK; goto i_done;
ErrorExit:
LsCsp_Exit();
i_done:
return( Status ); }
/*++
Function:
LsCsp_Exit
Description:
Free all resources used by this library.
Arguments:
Nothing.
Return:
A LICENSE_STATUS return code.
--*/
VOID LsCsp_Exit( void ) { if( InterlockedDecrement( &csp_InitCount ) > 0 ) { //
// someone is still using it.
//
return; }
if ( csp_abServerPrivateKey) { LocalFree( csp_abServerPrivateKey ); } csp_abServerPrivateKey = NULL;
if ( csp_abServerCertificate ) { LocalFree( csp_abServerCertificate ); } csp_abServerCertificate = NULL;
if( csp_abServerX509Cert ) { LocalFree( csp_abServerX509Cert ); } csp_abServerX509Cert = NULL;
if( csp_abX509CertPrivateKey ) { LocalFree( csp_abX509CertPrivateKey ); } csp_abX509CertPrivateKey = NULL;
if( csp_abX509CertID ) { LocalFree( csp_abX509CertID ); } csp_abX509CertID = NULL;
if( csp_hMutex ) { CloseHandle( csp_hMutex ); } csp_hMutex = NULL;
return; }
/*++
Function:
LsCsp_GetServerData
Routine Description:
This function makes and return the microsoft terminal server certificate blob of data.
Arguments:
dwInfoDesired - What type of information to return.
pBlob - pointer to a location where the certificate blob data pointer is returned.
pdwServerCertLen - pointer to a location where the length of the above data is returned.
Return Value:
Windows Error Code.
--*/
LICENSE_STATUS LsCsp_GetServerData( LSCSPINFO Info, LPBYTE pBlob, LPDWORD pdwBlobLen ) { LICENSE_STATUS Status = LICENSE_STATUS_OK; DWORD dwDataLen; LPBYTE pbData;
ASSERT( pdwBlobLen != NULL );
if ((Info == LsCspInfo_PrivateKey) || (Info == LsCspInfo_X509CertPrivateKey)) { if (!IsSystemService()) { return LICENSE_STATUS_NO_PRIVATE_KEY; } }
ACQUIRE_EXCLUSIVE_ACCESS(csp_hMutex);
switch (Info) { case LsCspInfo_Certificate:
if( NULL == csp_abServerCertificate ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto gsd_done; }
pbData = csp_abServerCertificate; dwDataLen = csp_dwServerCertificateLen; break;
case LsCspInfo_X509Certificate:
//
// We may not have an X509 certificate if the hydra server has not
// requested one from the license server
//
if( NULL == csp_abServerX509Cert ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto gsd_done; }
pbData = csp_abServerX509Cert; dwDataLen = csp_dwServerX509CertLen; break;
case LsCspInfo_X509CertID:
//
// we will not have a certificate ID if the X509 certificate is not present
//
if( NULL == csp_abX509CertID ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto gsd_done; }
pbData = csp_abX509CertID; dwDataLen = csp_dwX509CertIDLen; break;
case LsCspInfo_PublicKey: pbData = csp_hscData.PublicKeyData.pBlob; dwDataLen = csp_hscData.PublicKeyData.wBlobLen; break;
case LsCspInfo_PrivateKey: if( NULL == csp_abServerPrivateKey ) { Status = LICENSE_STATUS_NO_PRIVATE_KEY; goto gsd_done; }
pbData = csp_abServerPrivateKey; dwDataLen = csp_dwServerPrivateKeyLen; break;
case LsCspInfo_X509CertPrivateKey: //
// The X509 certificate private key may not have been created.
//
if( NULL == csp_abX509CertPrivateKey ) { Status = LICENSE_STATUS_NO_PRIVATE_KEY; goto gsd_done; }
pbData = csp_abX509CertPrivateKey; dwDataLen = csp_dwX509CertPrivateKeyLen; break;
default: Status = LICENSE_STATUS_INVALID_INPUT; goto gsd_done; }
if (pBlob != NULL) { if (*pdwBlobLen < dwDataLen) { *pdwBlobLen = dwDataLen; Status = LICENSE_STATUS_INSUFFICIENT_BUFFER; } else { memcpy(pBlob, pbData, dwDataLen); *pdwBlobLen = dwDataLen; } } else { *pdwBlobLen = dwDataLen; }
gsd_done:
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex );
return( Status ); }
/*++
Function:
LsCsp_ReadProprietaryDataFromStorage
Description:
Read proprietary public/private info from registry/LSA secret Arguments:
None. Return:
LICENSE_STATUS --*/
LICENSE_STATUS LsCsp_ReadProprietaryDataFromStorage(PBYTE *ppbCert, DWORD *pcbCert, PBYTE *ppbPrivateKey, DWORD *pcbPrivateKey) { LICENSE_STATUS Status; HKEY hKey = NULL; DWORD dwDisp;
*ppbCert = *ppbPrivateKey = NULL; *pcbCert = *pcbPrivateKey = 0;
//
// Open the Registry
//
if( RegCreateKeyEx( HKEY_LOCAL_MACHINE, TEXT( HYDRA_CERT_REG_KEY ), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, &dwDisp ) != ERROR_SUCCESS ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto done; }
if ( RegQueryValueEx( hKey, TEXT( HYDRA_CERTIFICATE_VALUE ), NULL, // lpReserved
NULL, // lpType
NULL, // lpData
pcbCert) != ERROR_SUCCESS ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto done; }
Status = LsCsp_RetrieveSecret(PRIVATE_KEY_NAME, NULL, // pbKey
pcbPrivateKey);
if (LICENSE_STATUS_OK != Status) { goto done; }
*ppbCert = ( LPBYTE )LocalAlloc(LPTR,*pcbCert);
if (NULL == *ppbCert) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto done; }
*ppbPrivateKey = ( LPBYTE )LocalAlloc(LPTR,*pcbPrivateKey); if (NULL == *ppbPrivateKey) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto done; }
if ( RegQueryValueEx( hKey, TEXT( HYDRA_CERTIFICATE_VALUE ), NULL, // lpReserved
NULL, // lpType
*ppbCert, pcbCert) != ERROR_SUCCESS ) { Status = LICENSE_STATUS_NO_CERTIFICATE; goto done; }
Status = LsCsp_RetrieveSecret(PRIVATE_KEY_NAME, *ppbPrivateKey, pcbPrivateKey);
done: if (NULL != hKey) RegCloseKey(hKey);
if (Status != LICENSE_STATUS_OK) { if (NULL != *ppbCert) { LocalFree(*ppbCert); *ppbCert = NULL; *pcbCert = 0; }
if (NULL != *ppbPrivateKey) { LocalFree(*ppbPrivateKey); *ppbPrivateKey = NULL; *pcbPrivateKey = 0; } }
return Status; }
/*++
Function:
LsCsp_UseBuiltInCert
Description:
Initialize the global variables with hardcoded certificate. Arguments:
None. Return:
TRUE if the initialization is successful. --*/
BOOL LsCsp_UseBuiltInCert( void ) { LICENSE_STATUS Status;
ACQUIRE_EXCLUSIVE_ACCESS(csp_hMutex);
//
// Step 1, cleanup and initialization that happened
//
if (csp_abServerPrivateKey) { LocalFree( csp_abServerPrivateKey ); csp_abServerPrivateKey = NULL; }
if (csp_abServerCertificate) { LocalFree( csp_abServerCertificate ); csp_abServerCertificate = NULL; }
//
// Step 2, check for stored key and certificate
//
Status = LsCsp_ReadProprietaryDataFromStorage(&csp_abServerCertificate, &csp_dwServerCertificateLen,&csp_abServerPrivateKey, &csp_dwServerPrivateKeyLen);
if (LICENSE_STATUS_OK != Status) { PBYTE pbPrivateKey, pbCertificate; DWORD cbPrivateKey, cbCertificate;
//
// Step 3, if no stored info found, generate new info and store it
//
Status = CreateProprietaryKeyAndCert(&pbPrivateKey,&cbPrivateKey,&pbCertificate,&cbCertificate); if (LICENSE_STATUS_OK == Status) { LsCsp_SetServerData(LsCspInfo_PrivateKey,pbPrivateKey,cbPrivateKey);
LsCsp_SetServerData(LsCspInfo_Certificate,pbCertificate,cbCertificate); } }
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex ); return( Status == LICENSE_STATUS_OK ); }
/*++
Function:
LsCsp_InstallX509Certificate
Routine Description:
This function generates a private/public key pair and then finds a license server to issue an X509 certificate for the public key. It then stores the private key and certificate.
Arguments:
None.
Return Value:
LSCSP return code.
--*/
LICENSE_STATUS LsCsp_InstallX509Certificate(LPVOID lpParam) { DWORD cbPubKey, cbPrivKey, cbCertificate; LICENSE_STATUS Status; LPBYTE pbPubKey = NULL, pbPrivKey = NULL, pbCertificate = NULL; CERT_PUBLIC_KEY_INFO CapiPubKeyInfo; HWID Hwid; TLS_HANDLE hServer;
//
// before we go through the trouble of generating private and public
// keys, check if the license server is available.
//
hServer = TLSConnectToAnyLsServer(LS_DISCOVERY_TIMEOUT); if (NULL == hServer) { return( LICENSE_STATUS_NO_LICENSE_SERVER ); }
memset(&CapiPubKeyInfo, 0, sizeof(CapiPubKeyInfo));
//
// acquire exclusive access
//
ACQUIRE_EXCLUSIVE_ACCESS(csp_hMutex);
//
// Try to reload the certificate again, some other thread might have
// install the certificate already.
//
Status = ReloadCSPCertificateAndData(); if( LICENSE_STATUS_OK == Status ) { goto done; }
//
// Generate a private/public key pair
//
Status = GenerateRsaKeyPair( &pbPubKey, &cbPubKey, &pbPrivKey, &cbPrivKey, RSA_KEY_LEN ); if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot generate RSA keypair\n" ); #endif
goto done; }
//
// convert the Bsafe public key into a CAPI public key
//
Status = Bsafe2CapiPubKey( &CapiPubKeyInfo, pbPubKey, cbPubKey );
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot convert Bsafe Key to CAPI key\n" ); #endif
goto done; }
//
// generate a new hardware ID
//
Status = GenerateMachineHWID( &Hwid );
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot generate certificate ID\n" ); #endif
goto done; }
//
// sends the certificate request to the license server
//
Status = RequestCertificate( hServer, &CapiPubKeyInfo, &pbCertificate, &cbCertificate, &Hwid );
TLSDisconnectFromServer( hServer ); hServer = NULL;
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: error requesting terminal server certificate: %x\n", Status ); #endif
goto done; }
//
// store the certificate identifier
//
Status = LsCsp_SetServerData( LsCspInfo_X509CertID, ( LPBYTE )&Hwid, sizeof( Hwid ) );
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot store terminal server certificate ID : %d\n", Status ); #endif
goto done; } //
// Stores the certificate and resets the global variable pointing
// to the X509 certificate.
//
Status = LsCsp_SetServerData( LsCspInfo_X509Certificate, pbCertificate, cbCertificate );
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot store terminal server certificate : %d\n", Status ); #endif
goto done; }
//
// Stores the private key and resets the global variable pointing to the
// private key.
//
Status = LsCsp_SetServerData( LsCspInfo_X509CertPrivateKey, pbPrivKey, cbPrivKey );
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot store terminal server private key %d\n", Status ); #endif
goto done; }
//
// Store the public key so we can verify at startup time
//
Status = LsCsp_StoreSecret( X509_CERT_PUBLIC_KEY_NAME, pbPubKey, cbPubKey );
if( LICENSE_STATUS_OK != Status ) { #if DBG
DbgPrint( "LSCSP: LsCsp_InstallX509Certificate: cannot store terminal server public key : %d\n", Status ); #endif
}
done:
if (NULL != hServer) { TLSDisconnectFromServer( hServer ); hServer = NULL; }
//
// release exclusive access
//
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex );
if( pbCertificate ) { LocalFree(pbCertificate); }
if( pbPrivKey ) { LocalFree( pbPrivKey ); }
if( pbPubKey ) { LocalFree( pbPubKey ); }
FreeCapiPubKey( &CapiPubKeyInfo );
return( Status ); }
/*++
Function:
RequestCertificate
Routine Description:
Request a certificate from the license server
Arguments:
hServer - handle to license server pPubKeyInfo - The public key info to be included in the certificate ppbCertificate - The new certificate pcbCertificate - size of the certificate pHwid - The hardware ID that is used to identify the certificate
Return:
LICENSE_STATUS return code
--*/
LICENSE_STATUS RequestCertificate( TLS_HANDLE hServer, PCERT_PUBLIC_KEY_INFO pPubKeyInfo, LPBYTE * ppbCertificate, LPDWORD pcbCertificate, HWID * pHwid ) { LSHydraCertRequest CertRequest; LICENSE_STATUS Status; DWORD dwRpcCode, dwResult, cbChallengeData; LPBYTE pbChallengeData = NULL;
if( ( NULL == ppbCertificate ) || ( NULL == hServer ) || ( NULL == pPubKeyInfo ) || ( NULL == pcbCertificate ) ) { return( LICENSE_STATUS_INVALID_INPUT ); }
*ppbCertificate = NULL; *pcbCertificate = 0;
memset( &CertRequest, 0, sizeof( CertRequest ) );
CertRequest.dwHydraVersion = 0x00050000; LsCsp_EncryptHwid( pHwid, NULL, &CertRequest.cbEncryptedHwid );
CertRequest.pbEncryptedHwid = LocalAlloc( LPTR, CertRequest.cbEncryptedHwid );
if( NULL == CertRequest.pbEncryptedHwid ) { return LICENSE_STATUS_OUT_OF_MEMORY; }
Status = LsCsp_EncryptHwid( pHwid, CertRequest.pbEncryptedHwid, &CertRequest.cbEncryptedHwid );
if( LICENSE_STATUS_OK != Status ) { goto done; } //
// get the subject RDN
//
Status = GetSubjectRdn( &CertRequest.szSubjectRdn );
if( LICENSE_STATUS_OK != Status ) { goto done; }
CertRequest.SubjectPublicKeyInfo = pPubKeyInfo;
//
// request an X509 certificate from the license server
//
dwRpcCode = TLSRequestTermServCert(hServer, &CertRequest, &cbChallengeData, &pbChallengeData, &dwResult );
if( ( RPC_S_OK != dwRpcCode ) || ( LSERVER_S_SUCCESS != dwResult ) ) { Status = LICENSE_STATUS_CERTIFICATE_REQUEST_ERROR; goto done; }
dwRpcCode = TLSRetrieveTermServCert( hServer, cbChallengeData, pbChallengeData, pcbCertificate, ppbCertificate, &dwResult );
if( ( RPC_S_OK != dwRpcCode ) || ( LSERVER_ERROR_BASE <= dwResult ) ) {
Status = LICENSE_STATUS_CERTIFICATE_REQUEST_ERROR; }
done:
if( CertRequest.pbEncryptedHwid ) { LocalFree( CertRequest.pbEncryptedHwid ); }
if( CertRequest.szSubjectRdn ) { LocalFree( CertRequest.szSubjectRdn ); }
if( pbChallengeData ) { LocalFree( pbChallengeData ); }
return( Status ); }
/*++
Function:
GetSubjectRdn
Routine Description:
Construct the subject RDN for a certificate request
Argument:
ppSubjectRdn - Return pointer to the subject RDN
Return:
LICENSE_STATUS_OK if successful or a LICENSE_STATUS error code.
--*/
LICENSE_STATUS GetSubjectRdn( LPTSTR * ppSubjectRdn ) { TCHAR ComputerName[ MAX_COMPUTERNAME_LENGTH + 1 ]; DWORD RdnLen = 0, ComputerNameLen = MAX_COMPUTERNAME_LENGTH + 1;
//
// use the computer name uas the common name
//
GetComputerName( ComputerName, &ComputerNameLen );
RdnLen += wcslen( TEXT( RDN_COMMON_NAME ) ); RdnLen += ComputerNameLen + 1; RdnLen = RdnLen * sizeof( TCHAR );
*ppSubjectRdn = LocalAlloc( LPTR, RdnLen );
if( NULL == *ppSubjectRdn ) { return( LICENSE_STATUS_OUT_OF_MEMORY ); }
wsprintf( *ppSubjectRdn, L"%s%s", TEXT( RDN_COMMON_NAME ), ComputerName ); return( LICENSE_STATUS_OK ); }
/*++
Function:
GenerateMachineHWID
Routine Description:
Generate a hardware ID for this machine
Arguments:
pHwid - Return value of the HWID
Return:
LICENSE_STATUS_OK if successful or a LICENSE_STATUS error code
--*/
LICENSE_STATUS GenerateMachineHWID( PHWID pHwid ) { OSVERSIONINFO osvInfo; DWORD cbCertId; LPBYTE pbCertId = NULL;
if( NULL == pHwid ) { return( LICENSE_STATUS_INVALID_INPUT ); }
//
// Create the HWID
//
memset( &osvInfo, 0, sizeof( OSVERSIONINFO ) ); osvInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); GetVersionEx( &osvInfo );
pHwid->dwPlatformID = osvInfo.dwPlatformId;
GenerateRandomBits( ( LPBYTE )&( pHwid->Data1 ), sizeof( DWORD ) ); GenerateRandomBits( ( LPBYTE )&( pHwid->Data2 ), sizeof( DWORD ) ); GenerateRandomBits( ( LPBYTE )&( pHwid->Data3 ), sizeof( DWORD ) ); GenerateRandomBits( ( LPBYTE )&( pHwid->Data4 ), sizeof( DWORD ) );
return( LICENSE_STATUS_OK ); }
/*++
Function:
LsCsp_EncryptHwid
Routine Description:
Encrypt the given hardward ID using the secret key shared by terminal and license servers. Arguments:
pHwid - The Hardware ID pbEncryptedHwid - The encrypted HWID pcbEncryptedHwid - Length of the encrypted HWID
Return:
LICENSE_STATUS_OK if successful or a LICENSE_STATUS error code otherwise.
--*/
LICENSE_STATUS LsCsp_EncryptHwid( PHWID pHwid, LPBYTE pbEncryptedHwid, LPDWORD pcbEncryptedHwid ) { LICENSE_STATUS Status; LPBYTE pbSecretKey = NULL; DWORD cbSecretKey = 0;
if( NULL == pcbEncryptedHwid ) { return( LICENSE_STATUS_INVALID_INPUT ); }
if( ( NULL == pbEncryptedHwid ) || ( sizeof( HWID ) > *pcbEncryptedHwid ) ) { *pcbEncryptedHwid = sizeof( HWID ); return( LICENSE_STATUS_INSUFFICIENT_BUFFER ); }
LicenseGetSecretKey( &cbSecretKey, NULL );
pbSecretKey = LocalAlloc( LPTR, cbSecretKey );
if( NULL == pbSecretKey ) { return( LICENSE_STATUS_OUT_OF_MEMORY ); }
//
// Get the secret key used for encrypting the HWID
//
Status = LicenseGetSecretKey( &cbSecretKey, pbSecretKey );
if( LICENSE_STATUS_OK != Status ) { goto done; }
Status = LicenseEncryptHwid( pHwid, pcbEncryptedHwid, pbEncryptedHwid, cbSecretKey, pbSecretKey );
done:
if( pbSecretKey ) { LocalFree( pbSecretKey ); }
return( Status );
}
/*++
Function:
LsCsp_DecryptHwid
Routine Description:
Decrypt the given hardware ID
Arguments:
pHwid - The decrypted hardware ID pbEncryptedHwid - The encrypted hardware ID cbEncryptedHwid - Length of the encrypted hardware ID
Return:
LICENSE_STATUS_OK if successful or a LICENSE_STATUS error code.
--*/
LICENSE_STATUS LsCsp_DecryptHwid( PHWID pHwid, LPBYTE pbEncryptedHwid, LPDWORD pcbEncryptedHwid ) { return( LICENSE_STATUS_OK ); }
/*++
Function:
LsCsp_StoreSecret
Description:
Use LSA to store a secret private key.
Arguments:
ptszKeyName - Name used to identify the secret private key. pbKey - Points to the secret private key. cbKey - Length of the private key.
Return:
A LICENSE_STATUS return code.
--*/
LICENSE_STATUS LsCsp_StoreSecret( PTCHAR ptszKeyName, BYTE * pbKey, DWORD cbKey ) { LSA_HANDLE PolicyHandle; UNICODE_STRING SecretKeyName; UNICODE_STRING SecretData; DWORD Status; if( ( NULL == ptszKeyName ) || ( 0xffff < cbKey) ) { return( LICENSE_STATUS_INVALID_INPUT ); }
//
// setup the UNICODE_STRINGs for the call.
//
InitLsaString( &SecretKeyName, ptszKeyName );
SecretData.Buffer = ( LPWSTR )pbKey; SecretData.Length = ( USHORT )cbKey; SecretData.MaximumLength = ( USHORT )cbKey;
Status = OpenPolicy( NULL, POLICY_CREATE_SECRET, &PolicyHandle );
if( ERROR_SUCCESS != Status ) { return ( LICENSE_STATUS_CANNOT_OPEN_SECRET_STORE ); }
Status = LsaStorePrivateData( PolicyHandle, &SecretKeyName, &SecretData );
LsaClose( PolicyHandle );
Status = LsaNtStatusToWinError( Status );
if( ERROR_SUCCESS != Status ) { return( LICENSE_STATUS_CANNOT_STORE_SECRET ); } return( LICENSE_STATUS_OK ); }
/*++
Function:
LsCsp_RetrieveSecret
Description:
Retrieve the secret private key that is stored by LSA.
Arguments:
ptszKeyName - The name used to identify the secret private key. ppbKey - Return value of the private key pcbKey - Length of the private key.
Return:
A LICENSE_STATUS return code.
--*/
LICENSE_STATUS LsCsp_RetrieveSecret( PTCHAR ptszKeyName, PBYTE pbKey, DWORD * pcbKey ) { LSA_HANDLE PolicyHandle; UNICODE_STRING SecretKeyName; UNICODE_STRING * pSecretData = NULL; DWORD Status; LICENSE_STATUS LicenseStatus = LICENSE_STATUS_OK;
if( ( NULL == ptszKeyName ) || ( NULL == pcbKey ) ) { return( ERROR_INVALID_PARAMETER ); }
//
// setup the UNICODE_STRINGs for the call.
//
InitLsaString( &SecretKeyName, ptszKeyName );
Status = OpenPolicy( NULL, POLICY_GET_PRIVATE_INFORMATION, &PolicyHandle );
if( ERROR_SUCCESS != Status ) { #if DBG
DbgPrint( "LSCSP: cannot open LSA policy handle: %x\n", Status ); #endif
return( LICENSE_STATUS_CANNOT_OPEN_SECRET_STORE ); }
Status = LsaNtStatusToWinError( LsaRetrievePrivateData( PolicyHandle, &SecretKeyName, &pSecretData ) );
LsaClose( PolicyHandle );
if (( ERROR_SUCCESS != Status ) || (NULL == pSecretData) || (pSecretData->Length == 0)) { #if DBG
DbgPrint( "LSCSP: cannot retrieve LSA data: %x\n", Status ); #endif
return( LICENSE_STATUS_CANNOT_RETRIEVE_SECRET ); }
if( NULL == pbKey ) { *pcbKey = pSecretData->Length; } else { if( pSecretData->Length > *pcbKey ) { LicenseStatus = LICENSE_STATUS_INSUFFICIENT_BUFFER; } else { CopyMemory( pbKey, pSecretData->Buffer, pSecretData->Length ); }
*pcbKey = pSecretData->Length; }
ZeroMemory( pSecretData->Buffer, pSecretData->Length ); LsaFreeMemory( pSecretData );
return( LicenseStatus ); }
/*++
Function:
OpenPolicy
Description:
Obtain an LSA policy handle used to perform subsequent LSA operations.
Arguments:
ServerName - The server which the handle should be obtained from. DesiredAccess - The access given to the handle PolicyHandle - The policy handle
Return:
A Win32 return code.
--*/
NTSTATUS OpenPolicy( LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle ) { LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_UNICODE_STRING ServerString; PLSA_UNICODE_STRING Server;
//
// Always initialize the object attributes to all zeroes.
//
ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
if( NULL != ServerName ) { //
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
//
InitLsaString(&ServerString, ServerName); Server = &ServerString;
} else { Server = NULL; }
//
// Attempt to open the policy.
//
return( LsaNtStatusToWinError( LsaOpenPolicy( Server, &ObjectAttributes, DesiredAccess, PolicyHandle ) ) ); }
/*++
Function:
InitLsaString
Description:
Initialize a UNICODE string to LSA UNICODE string format.
Arguments:
LsaString - the LSA UNICODE string. String - UNICODE string
Return:
Nothing.
--*/
void InitLsaString( PLSA_UNICODE_STRING LsaString, LPWSTR String ) { DWORD StringLength;
if( NULL == String ) { LsaString->Buffer = NULL; LsaString->Length = 0; LsaString->MaximumLength = 0; return; }
StringLength = lstrlenW( String ); LsaString->Buffer = String; LsaString->Length = ( USHORT ) StringLength * sizeof( WCHAR ); LsaString->MaximumLength=( USHORT )( StringLength + 1 ) * sizeof( WCHAR ); }
/*++
Function:
LsCsp_SetServerData
Description:
Saves the specified data.
Arguments:
Info - The data type of the data to be saved. pBlob - Points to the data to be saved. dwBlobLen - Length of the data to be saved.
Return:
A LICENSE_STATUS return code.
--*/
LICENSE_STATUS LsCsp_SetServerData( LSCSPINFO Info, LPBYTE pBlob, DWORD dwBlobLen ) { LICENSE_STATUS Status = LICENSE_STATUS_OK; DWORD dwResult, dwDisp, * pdwCspDataLen; LPTSTR lpRegValue; PWCHAR pwszKeyName; LPBYTE * ppCspData; HKEY hKey = NULL;
ASSERT( dwBlobLen != 0 ); ASSERT( pBlob != NULL );
ACQUIRE_EXCLUSIVE_ACCESS(csp_hMutex);
switch (Info) {
case LsCspInfo_Certificate:
//
// set proprietory certificate data
//
lpRegValue = TEXT( HYDRA_CERTIFICATE_VALUE ); ppCspData = &csp_abServerCertificate; pdwCspDataLen = &csp_dwServerCertificateLen;
break;
case LsCspInfo_X509Certificate:
//
// set X509 certificate data
//
lpRegValue = TEXT( HYDRA_X509_CERTIFICATE ); ppCspData = &csp_abServerX509Cert; pdwCspDataLen = &csp_dwServerX509CertLen;
break; case LsCspInfo_PrivateKey:
//
// set the private key that corresponds to the proprietory certificate
//
pwszKeyName = PRIVATE_KEY_NAME; ppCspData = &csp_abServerPrivateKey; pdwCspDataLen = &csp_dwServerPrivateKeyLen;
break;
case LsCspInfo_X509CertPrivateKey:
//
// set private key that corresponds to the X509 certificate
//
pwszKeyName = X509_CERT_PRIVATE_KEY_NAME; ppCspData = &csp_abX509CertPrivateKey; pdwCspDataLen = &csp_dwX509CertPrivateKeyLen;
break;
case LsCspInfo_X509CertID:
//
// Set the X509 certificate ID
//
lpRegValue = TEXT( HYDRA_X509_CERT_ID ); ppCspData = &csp_abX509CertID; pdwCspDataLen = &csp_dwX509CertIDLen;
break;
default:
Status = LICENSE_STATUS_INVALID_INPUT; goto i_done; }
if( ( LsCspInfo_X509CertPrivateKey == Info ) || ( LsCspInfo_PrivateKey == Info ) ) { //
// store secret key information
//
dwResult = LsCsp_StoreSecret( pwszKeyName, pBlob, dwBlobLen );
if( ERROR_SUCCESS != dwResult ) { Status = LICENSE_STATUS_WRITE_STORE_ERROR; goto i_done; } } else { //
// Open the Registry
//
if( RegCreateKeyEx( HKEY_LOCAL_MACHINE, TEXT( HYDRA_CERT_REG_KEY ), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp ) != ERROR_SUCCESS ) { Status = LICENSE_STATUS_WRITE_STORE_ERROR; goto i_done; }
//
// Sets the value in the registry
//
if( ERROR_SUCCESS != RegSetValueEx( hKey, lpRegValue, 0, REG_BINARY, pBlob, dwBlobLen ) ) { Status = LICENSE_STATUS_WRITE_STORE_ERROR; goto i_done; } } //
// reset the global data with the new data that we have just set
//
if ( *ppCspData ) { LocalFree( *ppCspData ); } *ppCspData = ( LPBYTE )LocalAlloc( LPTR, dwBlobLen );
if( NULL == *ppCspData ) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto i_done; }
memcpy( *ppCspData, pBlob, dwBlobLen ); *pdwCspDataLen = dwBlobLen; i_done:
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex );
if( hKey ) { RegCloseKey( hKey ); }
return( Status ); }
/*++
Function:
LsCsp_NukeServerData
Description:
Permanently deletes the specified server data.
Arguments:
Info - The type of data to nuke.
Returns:
A LICENSE_STATUS return code.
--*/
LICENSE_STATUS LsCsp_NukeServerData( LSCSPINFO Info ) { LICENSE_STATUS Status = LICENSE_STATUS_OK; LPTSTR lpRegValue; PWCHAR pwszKeyName; HKEY hKey = NULL; LPBYTE * ppCspData; DWORD * pdwCspDataLen; DWORD dwResult;
ACQUIRE_EXCLUSIVE_ACCESS(csp_hMutex);
switch (Info) {
case LsCspInfo_X509Certificate:
//
// delete X509 certificate data
//
lpRegValue = TEXT( HYDRA_X509_CERTIFICATE ); ppCspData = &csp_abServerX509Cert; pdwCspDataLen = &csp_dwServerX509CertLen;
break; case LsCspInfo_X509CertPrivateKey:
//
// delete the private key that corresponds to the X509 certificate
//
pwszKeyName = X509_CERT_PRIVATE_KEY_NAME; ppCspData = &csp_abX509CertPrivateKey; pdwCspDataLen = &csp_dwX509CertPrivateKeyLen;
break;
case LsCspInfo_X509CertID:
//
// delete the X509 certificate ID
//
lpRegValue = TEXT( HYDRA_X509_CERT_ID ); ppCspData = &csp_abX509CertID; pdwCspDataLen = &csp_dwX509CertIDLen;
break;
default:
Status = LICENSE_STATUS_INVALID_INPUT; goto i_done; }
if( (LsCspInfo_X509CertPrivateKey == Info ) || ( LsCspInfo_PrivateKey == Info ) ) { //
// delete secret info stored by LSA
//
dwResult = LsCsp_StoreSecret( pwszKeyName, NULL, 0 );
if( ERROR_SUCCESS != dwResult ) { Status = LICENSE_STATUS_WRITE_STORE_ERROR; goto i_done; } } else { //
// Delete the data kept in the registry
//
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT( HYDRA_CERT_REG_KEY ), 0, KEY_WRITE, &hKey ) != ERROR_SUCCESS ) { Status = LICENSE_STATUS_WRITE_STORE_ERROR; goto i_done; }
//
// Delete the value in the registry
//
if( ERROR_SUCCESS != RegDeleteValue( hKey, lpRegValue ) ) { Status = LICENSE_STATUS_WRITE_STORE_ERROR; goto i_done; } }
if ( *ppCspData ) { //
// free the memory allocated for the global variable.
//
LocalFree( *ppCspData ); *ppCspData = NULL; *pdwCspDataLen = 0; } i_done:
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex );
if( hKey ) { RegCloseKey( hKey ); }
return( Status ); }
/*++
Function:
GenerateKeyPair
Routine Description:
This function generates a private/public key pair.
Arguments:
ppbPublicKey - Return pointer to public Key pcbPublicKey - Size of public key ppbPrivateKey - Return pointer to private key pcbPrivateKey - size of private key dwKeyLen - Desired key length
Return Value:
LICENSE_STATUS return code.
--*/
LICENSE_STATUS GenerateRsaKeyPair( LPBYTE * ppbPublicKey, LPDWORD pcbPublicKey, LPBYTE * ppbPrivateKey, LPDWORD pcbPrivateKey, DWORD dwKeyLen ) { DWORD dwBits = dwKeyLen; LICENSE_STATUS Status = LICENSE_STATUS_OK;
*ppbPublicKey = NULL; *ppbPrivateKey = NULL;
//
// find out the size of the private and public key sizes and allocate
// memory for them.
//
dwBits = BSafeComputeKeySizes( pcbPublicKey, pcbPrivateKey, &dwBits );
*ppbPrivateKey = ( LPBYTE )LocalAlloc( LPTR, *pcbPrivateKey );
if( NULL == *ppbPrivateKey ) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto ErrorExit; }
*ppbPublicKey = ( LPBYTE )LocalAlloc( LPTR, *pcbPublicKey );
if( NULL == *ppbPublicKey ) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto ErrorExit; }
//
// generate the private/public key pair
//
if( !BSafeMakeKeyPair( ( LPBSAFE_PUB_KEY )*ppbPublicKey, ( LPBSAFE_PRV_KEY )*ppbPrivateKey, dwKeyLen) ) { Status = LICENSE_STATUS_CANNOT_MAKE_KEY_PAIR; goto ErrorExit; }
return( Status );
ErrorExit:
if( *ppbPublicKey ) { LocalFree( *ppbPublicKey ); *pcbPublicKey = 0; *ppbPublicKey = NULL; }
if( *ppbPrivateKey ) { LocalFree( *ppbPrivateKey ); *pcbPrivateKey = 0; *ppbPrivateKey = NULL; }
return( Status ); }
/*++
Function:
Bsafe2CapiPubKey
Routine Description:
Converts a Bsafe public key to a CAPI public key info structure
Arguments:
pCapiPubKeyInfo - Pointer to the CAPI public key info structure pbBsafePubKey - Pointer to the Bsafe public key cbBsafePubKey - size of the Bsafe public key
Returns:
LICENSE_STATUS return code.
--*/
LICENSE_STATUS Bsafe2CapiPubKey( PCERT_PUBLIC_KEY_INFO pCapiPubKeyInfo, LPBYTE pbBsafeKey, DWORD cbBsafeKey ) { PUBLICKEYSTRUC * pCapiPublicKey; RSAPUBKEY * pRsaPublicKey; LPBSAFE_PUB_KEY pBsafePubKey = ( LPBSAFE_PUB_KEY )pbBsafeKey; LPBYTE pbKeyMem = NULL, pbEncodedPubKey = NULL; DWORD cbKeyMem, dwError, cbEncodedPubKey = 0; LICENSE_STATUS Status; if( ( NULL == pbBsafeKey ) || ( 0 == cbBsafeKey ) ) { return( LICENSE_STATUS_INVALID_INPUT ); }
cbKeyMem = sizeof( PUBLICKEYSTRUC ) + sizeof( RSAPUBKEY ) + pBsafePubKey->keylen; pbKeyMem = ( LPBYTE )LocalAlloc( LPTR, cbKeyMem );
if( NULL == pbKeyMem ) { return( LICENSE_STATUS_OUT_OF_MEMORY ); }
//
// convert the Bsafe public key to a crypto API public key structure.
// Note: make this a key exchange public key
//
pCapiPublicKey = ( PUBLICKEYSTRUC * )pbKeyMem;
pCapiPublicKey->bType = PUBLICKEYBLOB; pCapiPublicKey->bVersion = CAPI_MAX_VERSION; pCapiPublicKey->reserved = 0; pCapiPublicKey->aiKeyAlg = CALG_RSA_KEYX;
pRsaPublicKey = ( RSAPUBKEY * )( pbKeyMem + sizeof( PUBLICKEYSTRUC ) ); pRsaPublicKey->magic = RSA1; pRsaPublicKey->bitlen = pBsafePubKey->bitlen; pRsaPublicKey->pubexp = pBsafePubKey->pubexp;
memcpy( pbKeyMem + sizeof( PUBLICKEYSTRUC ) + sizeof( RSAPUBKEY ), pbBsafeKey + sizeof( BSAFE_PUB_KEY ), pBsafePubKey->keylen );
//
// encode the public key structure
//
__try { if( CryptEncodeObject( X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB , pbKeyMem, NULL, &cbEncodedPubKey ) ) { pbEncodedPubKey = ( LPBYTE )LocalAlloc( LPTR, cbEncodedPubKey );
if( NULL == pbEncodedPubKey ) { Status = LICENSE_STATUS_OUT_OF_MEMORY; goto done; }
memset( pbEncodedPubKey, 0, cbEncodedPubKey );
if( !CryptEncodeObject( X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB , pbKeyMem, pbEncodedPubKey, &cbEncodedPubKey ) ) { Status = LICENSE_STATUS_ASN_ERROR; goto done; } } } __except( EXCEPTION_EXECUTE_HANDLER ) { DWORD dwExceptionCode = GetExceptionCode();
#if DBG
DbgPrint( "LICECSP: cannot encode server key pair: 0x%x\n", dwExceptionCode ); #endif
Status = LICENSE_STATUS_ASN_ERROR; goto done; }
//
// now we can initialize the CAPI public key info structure
//
memset( pCapiPubKeyInfo, 0, sizeof( CERT_PUBLIC_KEY_INFO ) ); pCapiPubKeyInfo->Algorithm.pszObjId = szOID_RSA_MD5RSA; pCapiPubKeyInfo->Algorithm.Parameters.cbData = 0; pCapiPubKeyInfo->Algorithm.Parameters.pbData = NULL;
pCapiPubKeyInfo->PublicKey.cbData = cbEncodedPubKey; pCapiPubKeyInfo->PublicKey.pbData = pbEncodedPubKey;
Status = LICENSE_STATUS_OK;
done:
if( pbKeyMem ) { LocalFree( pbKeyMem ); }
return( Status ); }
/*++
Function:
FreeCapiPubKey
Routine Description:
Free the memory in a capi pub key structure
Arguments:
pCapiPubKeyInfo - Pointer to the CAPI public key info structure
Returns:
Windows return code.
--*/
VOID FreeCapiPubKey( PCERT_PUBLIC_KEY_INFO pCapiPubKeyInfo ) { if( pCapiPubKeyInfo->Algorithm.Parameters.pbData ) { LocalFree( pCapiPubKeyInfo->Algorithm.Parameters.pbData ); pCapiPubKeyInfo->Algorithm.Parameters.pbData = NULL; }
if( pCapiPubKeyInfo->PublicKey.pbData ) { LocalFree( pCapiPubKeyInfo->PublicKey.pbData ); pCapiPubKeyInfo->PublicKey.pbData = NULL; }
return; }
//////////////////////////////////////////////////////////////////
DWORD VerifyTermServCertificate( DWORD cbCertLen, PBYTE pbCert, DWORD cbPrivateKeyLen, PBYTE pbPrivateKey ) /*++
Function : VerifyTermServCertificate
Routine Description:
Verify TermSrv's X509 Certificate issued License Server, caller must protect this call with critical section or mutex.
Arguments:
cbCertLen : size of TermSrv certificate. pbCertLen : Pointer to TermSrv certificate to be verify. cbPrivateKeyLen : Size of TermSrv private key. pbPrivateKey : pointer to TermSrv private key.
Returns:
TRUE/FALSE
--*/ { LICENSE_STATUS dwStatus = LICENSE_STATUS_OK; PBYTE pbPublicKeyInLsa = NULL; DWORD cbPublicKeyInLsa = 0;
PBYTE pbPublicKeyInCert = NULL; DWORD cbPublicKeyInCert = 0; DWORD pfDates;
CERT_PUBLIC_KEY_INFO CapiPubKeyInfoLsa; CERT_PUBLIC_KEY_INFO CapiPubKeyInfoCert;
if(0 == cbCertLen || NULL == pbCert || 0 == cbPrivateKeyLen || NULL == pbPrivateKey) { ASSERT( 0 != cbCertLen && NULL != pbCert && 0 != cbPrivateKeyLen && NULL != pbPrivateKey ); return LICENSE_STATUS_INVALID_INPUT; }
//
// try except here is to prevent memory leak
//
__try {
memset(&CapiPubKeyInfoLsa, 0, sizeof(CapiPubKeyInfoLsa)); memset(&CapiPubKeyInfoCert, 0, sizeof(CapiPubKeyInfoCert));
//
// Load the public key from LSA
//
dwStatus = LsCsp_RetrieveSecret( X509_CERT_PUBLIC_KEY_NAME, NULL, &cbPublicKeyInLsa );
if( LICENSE_STATUS_OK != dwStatus || 0 == cbPublicKeyInLsa ) {
#if DBG
DbgPrint( "LSCSP: VerifyTermServCertificate() No public key...\n" ); #endif
dwStatus = LICENSE_STATUS_CANNOT_RETRIEVE_SECRET; goto cleanup; }
// allocate memory
pbPublicKeyInLsa = (PBYTE)LocalAlloc(LPTR, cbPublicKeyInLsa); if(NULL == pbPublicKeyInLsa) { dwStatus = LICENSE_STATUS_OUT_OF_MEMORY; goto cleanup; }
dwStatus = LsCsp_RetrieveSecret( X509_CERT_PUBLIC_KEY_NAME, pbPublicKeyInLsa, &cbPublicKeyInLsa );
if( LICENSE_STATUS_OK != dwStatus || 0 == cbPublicKeyInLsa ) { dwStatus = LICENSE_STATUS_CANNOT_RETRIEVE_SECRET; goto cleanup; }
//
// Verify certificate and compare public key
//
//
// Try to avoid calling VerifyCertChain() twice.
//
cbPublicKeyInCert = 1024; pbPublicKeyInCert = (PBYTE)LocalAlloc(LPTR, cbPublicKeyInCert); if(NULL == pbPublicKeyInCert) { dwStatus = LICENSE_STATUS_OUT_OF_MEMORY; goto cleanup; }
pfDates = CERT_DATE_DONT_VALIDATE; dwStatus = VerifyCertChain( pbCert, cbCertLen, pbPublicKeyInCert, &cbPublicKeyInCert, &pfDates );
if(LICENSE_STATUS_OK != dwStatus && LICENSE_STATUS_INSUFFICIENT_BUFFER != dwStatus) {
#if DBG
DbgPrint( "LSCSP: VerifyCertChain() failed with error code %d\n", dwStatus ); #endif
goto cleanup; }
if( dwStatus == LICENSE_STATUS_INSUFFICIENT_BUFFER ) { if( NULL != pbPublicKeyInCert ) { LocalFree(pbPublicKeyInCert); }
pbPublicKeyInCert = (PBYTE)LocalAlloc(LPTR, cbPublicKeyInCert); if(NULL == pbPublicKeyInCert) { dwStatus = LICENSE_STATUS_OUT_OF_MEMORY; goto cleanup; }
pfDates = CERT_DATE_DONT_VALIDATE; dwStatus = VerifyCertChain( pbCert, cbCertLen, pbPublicKeyInCert, &cbPublicKeyInCert, &pfDates );
if(LICENSE_STATUS_OK != dwStatus) { goto cleanup; } }
dwStatus = Bsafe2CapiPubKey( &CapiPubKeyInfoCert, pbPublicKeyInCert, cbPublicKeyInCert );
if(LICENSE_STATUS_OK != dwStatus) { #if DBG
DbgPrint( "LSCSP: Bsafe2CapiPubKey() on public key in certificate failed with %d\n", dwStatus ); #endif
goto cleanup; }
dwStatus = Bsafe2CapiPubKey( &CapiPubKeyInfoLsa, pbPublicKeyInLsa, cbPublicKeyInLsa );
if(LICENSE_STATUS_OK != dwStatus) { #if DBG
DbgPrint( "LSCSP: Bsafe2CapiPubKey() on public key in LSA failed with %d\n", dwStatus ); #endif
goto cleanup; }
//
// compare public key
//
if( CapiPubKeyInfoCert.PublicKey.cbData != CapiPubKeyInfoLsa.PublicKey.cbData ) {
#if DBG
DbgPrint( "LSCSP: public key length mismatched %d %d\n", CapiPubKeyInfoCert.PublicKey.cbData, CapiPubKeyInfoLsa.PublicKey.cbData ); #endif
dwStatus = LICENSE_STATUS_INVALID_CERTIFICATE; } else if( memcmp( CapiPubKeyInfoCert.PublicKey.pbData, CapiPubKeyInfoLsa.PublicKey.pbData, CapiPubKeyInfoLsa.PublicKey.cbData ) != 0 ) {
#if DBG
DbgPrint( "LSCSP: public mismatched\n" ); #endif
dwStatus = LICENSE_STATUS_INVALID_CERTIFICATE; } } __except( EXCEPTION_EXECUTE_HANDLER ) { dwStatus = LICENSE_STATUS_INVALID_INPUT; }
cleanup:
FreeCapiPubKey( &CapiPubKeyInfoCert ); FreeCapiPubKey( &CapiPubKeyInfoLsa );
if( NULL != pbPublicKeyInLsa ) { LocalFree( pbPublicKeyInLsa ); }
if( NULL != pbPublicKeyInCert ) { LocalFree( pbPublicKeyInCert ); }
return dwStatus; }
//////////////////////////////////////////////////////////////////
LICENSE_STATUS ReloadCSPCertificateAndData() { BOOL bSuccess;
DWORD Status = LICENSE_STATUS_OK; LPBYTE i_csp_abServerX509Cert = NULL; DWORD i_csp_dwServerX509CertLen = 0; DWORD i_csp_dwX509CertPrivateKeyLen = 0; LPBYTE i_csp_abX509CertPrivateKey = NULL;
LPBYTE i_csp_abX509CertID = NULL; DWORD i_csp_dwX509CertIDLen = 0;
HKEY hKey = NULL; DWORD dwResult, dwDisp;
//
// Acquire exclusive access
//
ACQUIRE_EXCLUSIVE_ACCESS( csp_hMutex );
//
// Prevent re-loading of same certificate/private key
//
if( NULL == csp_abServerX509Cert || 0 == csp_dwServerX509CertLen || NULL == csp_abX509CertPrivateKey || 0 == csp_dwX509CertPrivateKeyLen || NULL == csp_abX509CertID || 0 == csp_dwX509CertIDLen ) {
//
// Open the Registry
//
if( RegCreateKeyEx( HKEY_LOCAL_MACHINE, TEXT( HYDRA_CERT_REG_KEY ), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp ) != ERROR_SUCCESS ) { Status = LICENSE_STATUS_NO_CERTIFICATE; } else { __try {
//
// Get the X509 certificate from the registry.
//
Status = LsCsp_GetBinaryData( hKey, TEXT( HYDRA_X509_CERTIFICATE ), &i_csp_abServerX509Cert, &i_csp_dwServerX509CertLen );
if( LICENSE_STATUS_OK == Status && 0 != i_csp_dwServerX509CertLen ) { //
// Get the corresponding private key from the store.
// It is not OK if we have the X509 certificate but not the
// private key that goes with it.
//
Status = LsCsp_RetrieveSecret( X509_CERT_PRIVATE_KEY_NAME, NULL, &i_csp_dwX509CertPrivateKeyLen );
if( LICENSE_STATUS_OK == Status ) { i_csp_abX509CertPrivateKey = LocalAlloc( LPTR, i_csp_dwX509CertPrivateKeyLen );
if( NULL != i_csp_abX509CertPrivateKey ) { Status = LsCsp_RetrieveSecret( X509_CERT_PRIVATE_KEY_NAME, i_csp_abX509CertPrivateKey, &i_csp_dwX509CertPrivateKeyLen );
if(LICENSE_STATUS_OK == Status) { //
// Get the certificate ID for the X509 certificate
//
Status = LsCsp_GetBinaryData( hKey, TEXT( HYDRA_X509_CERT_ID ), &i_csp_abX509CertID, &i_csp_dwX509CertIDLen ); } } else // memory allocate
{ Status = LICENSE_STATUS_OUT_OF_MEMORY; } } } else { Status = LICENSE_STATUS_NO_CERTIFICATE; }
} __except( EXCEPTION_EXECUTE_HANDLER ) { Status = LICENSE_STATUS_INVALID_INPUT; } }
//
// verify our certificate
//
if(LICENSE_STATUS_OK == Status) { Status = VerifyTermServCertificate( i_csp_dwServerX509CertLen, i_csp_abServerX509Cert, i_csp_dwX509CertPrivateKeyLen, i_csp_abX509CertPrivateKey );
if( LICENSE_STATUS_OK != Status ) { //
// Deleting the X509 certificate is enough.
//
RegDeleteValue( hKey, TEXT( HYDRA_X509_CERTIFICATE ) ); } } if(LICENSE_STATUS_OK != Status) { if( NULL != i_csp_abServerX509Cert ) { LocalFree( i_csp_abServerX509Cert ); } if( NULL != i_csp_abX509CertPrivateKey ) { LocalFree( i_csp_abX509CertPrivateKey ); }
if( NULL != i_csp_abX509CertID ) { LocalFree( i_csp_abX509CertID ); } } else { csp_abServerX509Cert = i_csp_abServerX509Cert; csp_dwServerX509CertLen = i_csp_dwServerX509CertLen;
csp_dwX509CertPrivateKeyLen = i_csp_dwX509CertPrivateKeyLen; csp_abX509CertPrivateKey = i_csp_abX509CertPrivateKey;
csp_abX509CertID = i_csp_abX509CertID; csp_dwX509CertIDLen = i_csp_dwX509CertIDLen; } }
RELEASE_EXCLUSIVE_ACCESS( csp_hMutex );
if (hKey) { RegCloseKey(hKey); }
return Status; }
LICENSE_STATUS CreateProprietaryKeyAndCert( PBYTE *ppbPrivateKey, DWORD *pcbPrivateKey, PBYTE *ppbServerCert, DWORD *pcbServerCert ) { #define MD5RSA 0x01;
#define RSAKEY 0x01;
LPBSAFE_PRV_KEY PRV; Hydra_Server_Cert Cert; DWORD KeyLen = 512; DWORD bits, j; DWORD dwPubSize, dwPrivSize; BYTE *kPublic; BYTE *kPrivate; MD5_CTX HashState; PBYTE pbData, pbTemp = NULL; DWORD dwTemp = 0; BYTE pbHash[0x48]; BYTE Output[0x48]; unsigned char prvmodulus[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xbd, 0x29, 0x20, 0x57, 0xd2, 0x3b, 0xf1, 0x07, 0xfa, 0xdf, 0xc1, 0x16, 0x31, 0xe4, 0x95, 0xea, 0xc1, 0x2a, 0x46, 0x2b, 0xad, 0x88, 0x57, 0x55, 0xf0, 0x57, 0x58, 0xc6, 0x6f, 0x95, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x83, 0xdd, 0x9d, 0xd0, 0x03, 0xb1, 0x5a, 0x9b, 0x9e, 0xb4, 0x63, 0x02, 0x43, 0x3e, 0xdf, 0xb0, 0x52, 0x83, 0x5f, 0x6a, 0x03, 0xe7, 0xd6, 0x78, 0x45, 0x83, 0x6a, 0x5b, 0xc4, 0xcb, 0xb1, 0x93, 0x00, 0x00, 0x00, 0x00, 0x65, 0x9d, 0x43, 0xe8, 0x48, 0x17, 0xcd, 0x29, 0x7e, 0xb9, 0x26, 0x5c, 0x79, 0x66, 0x58, 0x61, 0x72, 0x86, 0x6a, 0xa3, 0x63, 0xad, 0x63, 0xb8, 0xe1, 0x80, 0x4c, 0x0f, 0x36, 0x7d, 0xd9, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x75, 0x3f, 0xef, 0x5a, 0x01, 0x5f, 0xf6, 0x0e, 0xd7, 0xcd, 0x59, 0x1c, 0xc6, 0xec, 0xde, 0xf3, 0x5a, 0x03, 0x09, 0xff, 0xf5, 0x23, 0xcc, 0x90, 0x27, 0x1d, 0xaa, 0x29, 0x60, 0xde, 0x05, 0x6e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x17, 0x0e, 0x57, 0xf8, 0x9e, 0xd9, 0x5c, 0xf5, 0xb9, 0x3a, 0xfc, 0x0e, 0xe2, 0x33, 0x27, 0x59, 0x1d, 0xd0, 0x97, 0x4a, 0xb1, 0xb1, 0x1f, 0xc3, 0x37, 0xd1, 0xd6, 0xe6, 0x9b, 0x35, 0xab, 0x00, 0x00, 0x00, 0x00, 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8, 0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, 0xcf, 0x92, 0xcc, 0x33, 0x99, 0xe8, 0x08, 0x60, 0x17, 0x9a, 0x12, 0x9f, 0x24, 0xdd, 0xb1, 0x24, 0x99, 0xc7, 0x3a, 0xb8, 0x0a, 0x7b, 0x0d, 0xdd, 0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
PRV = (LPBSAFE_PRV_KEY)prvmodulus; PRV->magic = RSA2; PRV->keylen = 0x48; PRV->bitlen = 0x0200; PRV->datalen = 0x3f; PRV->pubexp = 0xc0887b5b;
Cert.dwVersion = 0x01; Cert.dwSigAlgID = MD5RSA; Cert.dwKeyAlgID = RSAKEY;
bits = KeyLen;
if (!BSafeComputeKeySizes(&dwPubSize, &dwPrivSize, &bits)) { return LICENSE_STATUS_INVALID_INPUT; }
if ((kPrivate = (BYTE *)LocalAlloc(LPTR,dwPrivSize)) == NULL) { return LICENSE_STATUS_OUT_OF_MEMORY; }
if ((kPublic = (BYTE *)LocalAlloc(LPTR,dwPubSize)) == NULL) { LocalFree(kPrivate); return LICENSE_STATUS_OUT_OF_MEMORY; }
if (!BSafeMakeKeyPair((LPBSAFE_PUB_KEY)kPublic, (LPBSAFE_PRV_KEY)kPrivate, KeyLen)) { LocalFree(kPrivate); LocalFree(kPublic); return LICENSE_STATUS_OUT_OF_MEMORY; }
// make proprietary format cert
Cert.PublicKeyData.wBlobType = BB_RSA_KEY_BLOB; Cert.PublicKeyData.wBlobLen = (WORD)dwPubSize; if( NULL == (Cert.PublicKeyData.pBlob = (PBYTE)LocalAlloc(LPTR,dwPubSize) ) ) { LocalFree(kPrivate); LocalFree(kPublic); return LICENSE_STATUS_OUT_OF_MEMORY; }
memcpy(Cert.PublicKeyData.pBlob, kPublic, dwPubSize);
dwTemp = 3*sizeof(DWORD) + 2*sizeof(WORD) + dwPubSize; if( NULL == (pbData = (PBYTE)LocalAlloc(LPTR,dwTemp)) ) { LocalFree(kPrivate); LocalFree(kPublic); LocalFree(Cert.PublicKeyData.pBlob); return LICENSE_STATUS_OUT_OF_MEMORY; }
pbTemp = pbData; memcpy(pbTemp, &Cert.dwVersion, sizeof(DWORD)); pbTemp += sizeof(DWORD); memcpy(pbTemp, &Cert.dwSigAlgID, sizeof(DWORD)); pbTemp += sizeof(DWORD);
memcpy(pbTemp, &Cert.dwKeyAlgID, sizeof(DWORD)); pbTemp += sizeof(DWORD);
memcpy(pbTemp, &Cert.PublicKeyData.wBlobType, sizeof(WORD)); pbTemp += sizeof(WORD);
memcpy(pbTemp, &Cert.PublicKeyData.wBlobLen, sizeof(WORD)); pbTemp += sizeof(WORD);
memcpy(pbTemp, Cert.PublicKeyData.pBlob, Cert.PublicKeyData.wBlobLen); pbTemp += Cert.PublicKeyData.wBlobLen;
// sign the cert
MD5Init(&HashState); MD5Update(&HashState, pbData, dwTemp); MD5Final(&HashState); LocalFree(pbData);
memset(pbHash, 0x00, 0x48); memset(pbHash, 0xff, 0x40);
pbHash[0x40-1] = 0; pbHash[0x40-2] = 1; pbHash[16] = 0; memcpy(pbHash, HashState.digest, 16);
BSafeDecPrivate(PRV, pbHash, Output);
Cert.SignatureBlob.wBlobType = BB_RSA_SIGNATURE_BLOB; Cert.SignatureBlob.wBlobLen = 0x48; if( NULL == (Cert.SignatureBlob.pBlob = (PBYTE)LocalAlloc(LPTR,Cert.SignatureBlob.wBlobLen)) ) { LocalFree(kPrivate); LocalFree(kPublic); LocalFree(Cert.PublicKeyData.pBlob); return LICENSE_STATUS_OUT_OF_MEMORY; }
memcpy(Cert.SignatureBlob.pBlob, Output, Cert.SignatureBlob.wBlobLen);
// Pack the Hydra_Server_Cert
dwTemp = 3*sizeof(DWORD) + 4*sizeof(WORD) + dwPubSize + 0x48;
if( NULL == (pbData = (PBYTE)LocalAlloc(LPTR,dwTemp)) ) { LocalFree(kPrivate); LocalFree(kPublic); LocalFree(Cert.PublicKeyData.pBlob); return LICENSE_STATUS_OUT_OF_MEMORY; }
pbTemp = pbData; memcpy(pbTemp, &Cert.dwVersion, sizeof(DWORD)); pbTemp += sizeof(DWORD);
memcpy(pbTemp, &Cert.dwSigAlgID, sizeof(DWORD)); pbTemp += sizeof(DWORD); memcpy(pbTemp, &Cert.dwKeyAlgID, sizeof(DWORD)); pbTemp += sizeof(DWORD);
memcpy(pbTemp, &Cert.PublicKeyData.wBlobType, sizeof(WORD)); pbTemp += sizeof(WORD);
memcpy(pbTemp, &Cert.PublicKeyData.wBlobLen, sizeof(WORD)); pbTemp += sizeof(WORD);
memcpy(pbTemp, Cert.PublicKeyData.pBlob, Cert.PublicKeyData.wBlobLen); pbTemp += Cert.PublicKeyData.wBlobLen;
memcpy(pbTemp, &Cert.SignatureBlob.wBlobType, sizeof(WORD)); pbTemp += sizeof(WORD);
memcpy(pbTemp, &Cert.SignatureBlob.wBlobLen, sizeof(WORD)); pbTemp += sizeof(WORD);
memcpy(pbTemp, Cert.SignatureBlob.pBlob, Cert.SignatureBlob.wBlobLen);
*ppbPrivateKey = kPrivate; *pcbPrivateKey = dwPrivSize;
*ppbServerCert = pbData; *pcbServerCert = dwTemp;
LocalFree(kPublic);
return LICENSE_STATUS_OK; }
//***************************************************************************
//
// IsSystemService
//
// returns TRUE if we are running as local system
//
//***************************************************************************
BOOL IsSystemService() { BOOL bOK = FALSE;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construct the local system SID
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SID LocalSystemSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID };
if ( !CheckTokenMembership ( NULL, &LocalSystemSid, &bOK ) ) { bOK = FALSE; }
return bOK; }
|