|
|
//+--------------------------------------------------------------------------
//
// 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; }
|