windows-nt/Source/XPSP1/NT/termsrv/license/tlserver/server/ch.cpp

916 lines
24 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1996
//
// File: ch.cpp
//
// Contents:
// All Clearing house related function
//
// History:
//
// Note:
//---------------------------------------------------------------------------
#include "pch.cpp"
#include "clrhouse.h"
#include "globals.h"
#include "gencert.h"
/*****************************************************************************
*****************************************************************************/
BOOL
TLSChainIssuerCertificate(
HCRYPTPROV hCryptProv,
HCERTSTORE hChainFromStore,
HCERTSTORE hChainToStore,
PCCERT_CONTEXT pSubjectContext
)
/*
*/
{
DWORD dwStatus = ERROR_SUCCESS;
PCCERT_CONTEXT pCertIssuer=NULL;
PCCERT_CONTEXT pCurrentSubject = NULL;
DWORD dwFlags;
//
// Increase reference count on Subject context.
//
// From MSDN: Currently, a copy is not made of the context, and the
// returned pointer to a context has the same value as the pointer to a
// context that was input.
//
pCurrentSubject = CertDuplicateCertificateContext(
pSubjectContext
);
while( TRUE )
{
dwFlags = CERT_STORE_SIGNATURE_FLAG;
pCertIssuer = CertGetIssuerCertificateFromStore(
hChainFromStore,
pCurrentSubject,
NULL,
&dwFlags
);
CertFreeCertificateContext(pCurrentSubject);
if(!pCertIssuer)
{
dwStatus = GetLastError();
break;
}
if(dwFlags & CERT_STORE_SIGNATURE_FLAG)
{
//
// we have invalid signature from certificate
//
dwStatus = TLS_E_INVALID_DATA;
break;
}
if(!CertAddCertificateContextToStore(
hChainToStore,
pCertIssuer,
CERT_STORE_ADD_REPLACE_EXISTING,
NULL
))
{
dwStatus = GetLastError();
break;
}
pCurrentSubject = pCertIssuer;
}
if(dwStatus == CRYPT_E_SELF_SIGNED)
{
dwStatus = ERROR_SUCCESS;
}
SetLastError(dwStatus);
if(pCertIssuer)
{
CertFreeCertificateContext(pCertIssuer);
}
return dwStatus == ERROR_SUCCESS;
}
/*****************************************************************************
*****************************************************************************/
HCERTSTORE
CertOpenRegistryStore(
HKEY hKeyType,
LPCTSTR szSubKey,
HCRYPTPROV hCryptProv,
HKEY* phKey
)
/*
*/
{
DWORD dwStatus;
HCERTSTORE hCertStore;
dwStatus=RegOpenKeyEx(hKeyType, szSubKey, 0, KEY_ALL_ACCESS, phKey);
if(dwStatus != ERROR_SUCCESS)
{
SetLastError(dwStatus);
return NULL;
}
hCertStore = CertOpenStore(
CERT_STORE_PROV_REG,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
(PVOID)*phKey
);
return hCertStore;
}
/*****************************************************************************
TransferCertFromStoreToStore()
*****************************************************************************/
DWORD
TransferCertFromStoreToStore(
HCERTSTORE hSrcStore,
HCERTSTORE hDestStore
)
/*
*/
{
PCCERT_CONTEXT pCertContext=NULL;
PCCERT_CONTEXT pPrevCertContext=NULL;
DWORD dwStatus=ERROR_SUCCESS;
do {
pCertContext = CertEnumCertificatesInStore(hSrcStore, pPrevCertContext);
if(pCertContext)
{
if(!CertAddCertificateContextToStore(
hDestStore,
pCertContext,
CERT_STORE_ADD_REPLACE_EXISTING,
NULL
))
{
dwStatus = GetLastError();
break;
}
}
pPrevCertContext = pCertContext;
} while( pCertContext != NULL );
if(GetLastError() == CRYPT_E_NOT_FOUND)
{
dwStatus = ERROR_SUCCESS;
}
return dwStatus;
}
/*****************************************************************************
LSSaveCertAsPKCS7()
*****************************************************************************/
DWORD
TLSSaveCertAsPKCS7(
PBYTE pbCert,
DWORD cbCert,
PBYTE* ppbEncodedCert,
PDWORD pcbEncodedCert
)
/*
*/
{
DWORD dwStatus=ERROR_SUCCESS;
HCRYPTPROV hCryptProv=g_hCryptProv;
HCERTSTORE hStore=NULL;
PCCERT_CONTEXT pCertContext=NULL;
do {
//
// Must have call CryptoInit()
//if(!CryptAcquireContext(&hCryptProv, _TEXT(KEYCONTAINER), MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
//{
// LSLogEvent(EVENTLOG_ERROR_TYPE, TLS_E_CRYPT_ACQUIRE_CONTEXT, dwStatus=GetLastError());
// break;
//}
hStore=CertOpenStore(
CERT_STORE_PROV_MEMORY,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
NULL
);
if(!hStore)
{
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_GENERATECLIENTELICENSE,
TLS_E_OPEN_CERT_STORE,
dwStatus=GetLastError()
);
break;
}
pCertContext = CertCreateCertificateContext(
X509_ASN_ENCODING,
pbCert,
cbCert
);
if(!pCertContext)
{
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_GENERATECLIENTELICENSE,
TLS_E_CREATE_CERTCONTEXT,
dwStatus=GetLastError()
);
break;
}
//
// always start from empty so CERT_STORE_ADD_ALWAYS
if(!CertAddCertificateContextToStore(
hStore,
pCertContext,
CERT_STORE_ADD_ALWAYS,
NULL
))
{
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_GENERATECLIENTELICENSE,
TLS_E_ADD_CERT_TO_STORE,
dwStatus=GetLastError()
);
break;
}
#ifdef ENFORCE_LICENSING
if(g_bHasHydraCert && g_hCaStore)
{
if(!TLSChainIssuerCertificate(
hCryptProv,
g_hCaStore,
hStore,
pCertContext
))
{
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_GENERATECLIENTELICENSE,
TLS_E_ADD_CERT_TO_STORE,
dwStatus=GetLastError()
);
break;
}
}
#endif
CRYPT_DATA_BLOB saveBlob;
memset(&saveBlob, 0, sizeof(saveBlob));
// save certificate into memory
if(!CertSaveStore(hStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
LICENSE_BLOB_SAVEAS_TYPE,
CERT_STORE_SAVE_TO_MEMORY,
&saveBlob,
0) && (dwStatus=GetLastError()) != ERROR_MORE_DATA)
{
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_GENERATECLIENTELICENSE,
TLS_E_SAVE_STORE,
dwStatus=GetLastError()
);
break;
}
if(!(saveBlob.pbData = (PBYTE)midl_user_allocate(saveBlob.cbData)))
{
dwStatus=GetLastError();
break;
}
// save certificate into memory
if(!CertSaveStore(hStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
LICENSE_BLOB_SAVEAS_TYPE,
CERT_STORE_SAVE_TO_MEMORY,
&saveBlob,
0))
{
TLSLogEvent(
EVENTLOG_ERROR_TYPE,
TLS_E_GENERATECLIENTELICENSE,
TLS_E_SAVE_STORE,
dwStatus=GetLastError()
);
break;
}
*ppbEncodedCert = saveBlob.pbData;
*pcbEncodedCert = saveBlob.cbData;
} while(FALSE);
if(pCertContext)
{
CertFreeCertificateContext(pCertContext);
}
if(hStore)
{
CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
return (dwStatus == ERROR_SUCCESS) ? ERROR_SUCCESS : TLS_E_SAVE_STORE;
}
//--------------------------------------------------------------------------
//
static LONG
OpenCertRegStore(
LPCTSTR szSubKey,
PHKEY phKey
)
/*
*/
{
DWORD dwDisposition;
return RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
phKey,
&dwDisposition
);
}
//--------------------------------------------------------------------------
//
static DWORD
IsHydraRootOIDInCert(
PCCERT_CONTEXT pCertContext,
DWORD dwKeyType
)
/*
*/
{
BOOL bFound=FALSE;
PCERT_INFO pCertInfo = pCertContext->pCertInfo;
PCERT_EXTENSION pCertExtension=pCertInfo->rgExtension;
PCERT_PUBLIC_KEY_INFO pbPublicKey=NULL;
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwSize = 0;
//
// Must have a CH root extension.
//
for(DWORD i=0; i < pCertInfo->cExtension && bFound == FALSE; i++, pCertExtension++)
{
bFound=(strcmp(pCertExtension->pszObjId, szOID_PKIX_HYDRA_CERT_ROOT) == 0);
}
if(bFound == TRUE)
{
//
// Public Key must be the same
//
dwStatus = TLSExportPublicKey(
g_hCryptProv,
dwKeyType,
&dwSize,
&pbPublicKey
);
if(dwStatus == ERROR_SUCCESS)
{
bFound = CertComparePublicKeyInfo(
X509_ASN_ENCODING,
pbPublicKey,
&(pCertContext->pCertInfo->SubjectPublicKeyInfo)
);
if(bFound == FALSE)
{
dwStatus = TLS_E_CH_INSTALL_NON_LSCERTIFICATE;
}
}
}
else
{
dwStatus = TLS_E_CH_LSCERTIFICATE_NOTFOUND;
}
FreeMemory(pbPublicKey);
return dwStatus;
}
//---------------------------------------------------------------------------
// Functions:
// IsCertificateLicenseServerCertificate()
//
// Abstract:
// Find License Server certificate in PKCS 7 certificate blob
//
// Parameters:
// hCryptProv - Cryto. Provider
// cbPKCS7Cert - Size of PKCS7 certificate.
// pbPKCS7Cert - pointer to PKCS7 certificate
// cbLsCert - size of encoded license server certificate.
// pbLsCert - pointer to pointer to receive license server encoded certificate.
//
// Returns:
// ERROR_SUCCESS
// TLS_E_INVALID_DATA
// Crypto. error code.
//---------------------------------------------------------------------------
DWORD
IsCertificateLicenseServerCertificate(
IN HCRYPTPROV hCryptProv,
IN DWORD dwCertType,
IN DWORD cbPKCS7Cert,
IN PBYTE pbPKCS7Cert,
IN OUT DWORD* cbLsCert,
IN OUT PBYTE* pbLsCert
)
/*
*/
{
//
// Certificate must be in PCKS 7 format.
//
DWORD dwStatus=ERROR_SUCCESS;
HCERTSTORE hCertStore=NULL;
PCCERT_CONTEXT pPrevCertContext=NULL;
PCCERT_CONTEXT pCertContext=NULL;
CRYPT_DATA_BLOB Serialized;
Serialized.pbData = pbPKCS7Cert;
Serialized.cbData = cbPKCS7Cert;
hCertStore = CertOpenStore(
CERT_STORE_PROV_PKCS7,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
&Serialized
);
if(!hCertStore)
{
return dwStatus=GetLastError();
}
//
// enumerate all certificate and find certificate with our extension.
//
do {
pCertContext = CertEnumCertificatesInStore(
hCertStore,
pPrevCertContext
);
if(pCertContext)
{
dwStatus = IsHydraRootOIDInCert(
pCertContext,
dwCertType
);
if(dwStatus == ERROR_SUCCESS)
{
//
// this is our certificate.
//
*pbLsCert = (PBYTE)AllocateMemory(*cbLsCert = pCertContext->cbCertEncoded);
if(*pbLsCert)
{
memcpy(
*pbLsCert,
pCertContext->pbCertEncoded,
pCertContext->cbCertEncoded
);
}
else
{
dwStatus = GetLastError();
}
break;
}
else if(dwStatus == TLS_E_CH_INSTALL_NON_LSCERTIFICATE)
{
break;
}
//
// reset status code.
//
dwStatus = ERROR_SUCCESS;
}
pPrevCertContext = pCertContext;
} while( pCertContext != NULL );
if(pCertContext != NULL)
{
CertFreeCertificateContext(pPrevCertContext);
}
if(hCertStore)
{
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
return dwStatus;
}
//---------------------------------------------------------------------------
// Functions:
// LSSaveCertificateToReg()
//
// Abstract:
//
//
// Parameters:
// hCryptProv - Cryto. Provider
//
//
//
//
//
// Returns:
//
//
//
//---------------------------------------------------------------------------
DWORD
TLSSaveRootCertificateToReg(
HCRYPTPROV hCryptProv,
HKEY hKey,
DWORD cbEncodedCert,
PBYTE pbEncodedCert
)
/*
*/
{
PCCERT_CONTEXT pCertContext=NULL;
HCERTSTORE hCertSaveStore=NULL;
DWORD dwStatus=ERROR_SUCCESS;
do {
hCertSaveStore = CertOpenStore(
CERT_STORE_PROV_REG,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
(PVOID)hKey
);
if(!hCertSaveStore)
{
// dwStatus = GetLastError();
dwStatus = TLS_E_INVALID_DATA;
break;
}
pCertContext = CertCreateCertificateContext(
X509_ASN_ENCODING,
pbEncodedCert,
cbEncodedCert
);
if(!pCertContext)
{
// dwStatus = GetLastError();
dwStatus = TLS_E_INVALID_DATA;
break;
}
if(!CertAddCertificateContextToStore(
hCertSaveStore,
pCertContext,
CERT_STORE_ADD_REPLACE_EXISTING,
NULL
))
{
dwStatus=GetLastError();
}
} while(FALSE);
if(pCertContext)
{
CertFreeCertificateContext( pCertContext );
}
if(hCertSaveStore)
{
CertCloseStore(
hCertSaveStore,
CERT_CLOSE_STORE_FORCE_FLAG
);
}
return dwStatus;
}
//---------------------------------------------------------------------------
// Functions:
// LSSaveCertificateToReg()
//
// Abstract:
//
//
// Parameters:
// hCryptProv - Cryto. Provider
//
//
//
//
//
// Returns:
//
//
//
//---------------------------------------------------------------------------
DWORD
TLSSaveCertificateToReg(
HCRYPTPROV hCryptProv,
HKEY hKey,
DWORD cbPKCS7Cert,
PBYTE pbPKCS7Cert
)
/*
*/
{
//
// Certificate must be in PCKS 7 format.
//
DWORD dwStatus=ERROR_SUCCESS;
HCERTSTORE hCertOpenStore=NULL;
HCERTSTORE hCertSaveStore=NULL;
PCCERT_CONTEXT pPrevCertContext=NULL;
PCCERT_CONTEXT pCertContext=NULL;
CRYPT_DATA_BLOB Serialized;
Serialized.pbData = pbPKCS7Cert;
Serialized.cbData = cbPKCS7Cert;
hCertOpenStore = CertOpenStore(
CERT_STORE_PROV_PKCS7,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
&Serialized
);
if(!hCertOpenStore)
{
// dwStatus = GetLastError();
dwStatus = TLS_E_INVALID_DATA;
goto cleanup;
}
hCertSaveStore = CertOpenStore(
CERT_STORE_PROV_REG,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
(PVOID)hKey
);
if(!hCertSaveStore)
{
dwStatus = TLS_E_INVALID_DATA;
goto cleanup;
}
dwStatus = TransferCertFromStoreToStore(
hCertOpenStore,
hCertSaveStore
);
cleanup:
if(hCertSaveStore)
{
CertCloseStore(
hCertSaveStore,
CERT_CLOSE_STORE_FORCE_FLAG
);
}
if(hCertOpenStore)
{
CertCloseStore(
hCertOpenStore,
CERT_CLOSE_STORE_FORCE_FLAG
);
}
return dwStatus;
}
//---------------------------------------------------------------------------
// Functions:
// LSSaveRootCertificatesToStore()
//
// Abstract:
//
// Save root certificate to license server certificate store.
//
// Parameters:
// hCryptProv - Cryto. Provider
// cbSignatureCert - size of root's signature certificate.
// pbSignatureCert - pointer to root's signature certificate.
// cbExchangeCert - size of root's exchange certficate.
// pbExchangeCert - pointer to root's exchange certificate
//
// Returns:
//
//---------------------------------------------------------------------------
DWORD
TLSSaveRootCertificatesToStore(
IN HCRYPTPROV hCryptProv,
IN DWORD cbSignatureCert,
IN PBYTE pbSignatureCert,
IN DWORD cbExchangeCert,
IN PBYTE pbExchangeCert
)
/*
*/
{
HKEY hKey;
LONG status=ERROR_SUCCESS;
if(cbSignatureCert == 0 && cbExchangeCert == 0)
{
return status = TLS_E_INVALID_DATA;
}
if(cbSignatureCert)
{
status = OpenCertRegStore(
LSERVER_CERTIFICATE_REG_ROOT_SIGNATURE,
&hKey
);
if(status != ERROR_SUCCESS)
return status;
status = TLSSaveRootCertificateToReg(
hCryptProv,
hKey,
cbSignatureCert,
pbSignatureCert
);
RegCloseKey(hKey);
if(status != ERROR_SUCCESS)
return status;
}
if(cbExchangeCert)
{
status = OpenCertRegStore(
LSERVER_CERTIFICATE_REG_ROOT_EXCHANGE,
&hKey
);
if(status != ERROR_SUCCESS)
return status;
status=TLSSaveRootCertificateToReg(
hCryptProv,
hKey,
cbExchangeCert,
pbExchangeCert
);
RegCloseKey(hKey);
}
return status;
}
//---------------------------------------------------------------------------
// Functions:
// LSSaveCertificatesToStore()
//
// Abstract:
//
//
// Parameters:
// hCryptProv - Cryto. Provider
//
//
//
//
//
// Returns:
//
//
//
//---------------------------------------------------------------------------
DWORD
TLSSaveCertificatesToStore(
IN HCRYPTPROV hCryptProv,
IN DWORD dwCertType,
IN DWORD dwCertLevel,
IN DWORD cbSignatureCert,
IN PBYTE pbSignatureCert,
IN DWORD cbExchangeCert,
IN PBYTE pbExchangeCert
)
/*
*/
{
HKEY hKey;
LONG status = ERROR_SUCCESS;
LPTSTR szRegSignature;
LPTSTR szRegExchange;
switch(dwCertType)
{
case CERTIFICATE_CA_TYPE:
szRegSignature = LSERVER_CERTIFICATE_REG_CA_SIGNATURE;
szRegExchange = LSERVER_CERTIFICATE_REG_CA_EXCHANGE;
break;
case CERTITICATE_MF_TYPE:
szRegSignature = LSERVER_CERTIFICATE_REG_MF_SIGNATURE;
szRegExchange = LSERVER_CERTIFICATE_REG_MF_EXCHANGE;
break;
case CERTIFICATE_CH_TYPE:
szRegSignature = LSERVER_CERTIFICATE_REG_CH_SIGNATURE;
szRegExchange = LSERVER_CERTIFICATE_REG_CH_EXCHANGE;
break;
default:
status = TLS_E_INVALID_DATA;
return status;
}
if(cbSignatureCert)
{
status = OpenCertRegStore(szRegSignature, &hKey);
if(status != ERROR_SUCCESS)
return status;
status=TLSSaveCertificateToReg(
hCryptProv,
hKey,
cbSignatureCert,
pbSignatureCert
);
RegCloseKey(hKey);
if(status != ERROR_SUCCESS)
return status;
}
if(cbExchangeCert)
{
status = OpenCertRegStore(szRegExchange, &hKey);
if(status != ERROR_SUCCESS)
return status;
status=TLSSaveCertificateToReg(
hCryptProv,
hKey,
cbExchangeCert,
pbExchangeCert
);
RegCloseKey(hKey);
}
return status;
}