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.
254 lines
7.9 KiB
254 lines
7.9 KiB
// WinRegCertStore.cpp - Implementation of CWinRegCertStore class
|
|
//
|
|
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
|
|
// 2000. This computer program includes Confidential, Proprietary
|
|
// Information and is a Trade Secret of Schlumberger Technology Corp. All
|
|
// use, disclosure, and/or reproduction is prohibited unless authorized
|
|
// in writing. All Rights Reserved.
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <windows.h>
|
|
|
|
#include "scuOsExc.h"
|
|
#include "pkiWinRegCertStore.h"
|
|
#include "pkiX509Cert.h"
|
|
|
|
using namespace pki;
|
|
using namespace std;
|
|
|
|
CWinRegCertStore::CWinRegCertStore(string strCertStore) : m_hCertStore(0)
|
|
{
|
|
|
|
// Open certificate store
|
|
|
|
scu::AutoArrayPtr<WCHAR> aapWCertStore = ToWideChar(strCertStore);
|
|
|
|
HCRYPTPROV hProv = 0;
|
|
m_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
|
|
CERT_SYSTEM_STORE_CURRENT_USER, aapWCertStore.Get());
|
|
if(!m_hCertStore)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
}
|
|
|
|
CWinRegCertStore::~CWinRegCertStore()
|
|
{
|
|
try
|
|
{
|
|
// Close certificate store
|
|
|
|
if(m_hCertStore)
|
|
CertCloseStore(m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
|
}
|
|
catch(...) {}
|
|
|
|
}
|
|
|
|
void CWinRegCertStore::StoreUserCert(string const &strCert, DWORD const dwKeySpec,
|
|
string const &strContName, string const &strProvName,
|
|
string const &strFriendlyName)
|
|
{
|
|
|
|
// Create cert context
|
|
|
|
PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING,(BYTE*)strCert.c_str(),strCert.size());
|
|
if(!pCertContext)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
// Set the cert context properties
|
|
|
|
CRYPT_KEY_PROV_INFO KeyProvInfo;
|
|
|
|
scu::AutoArrayPtr<WCHAR> aapWContainerName = ToWideChar(strContName);
|
|
scu::AutoArrayPtr<WCHAR> aapWProvName = ToWideChar(strProvName);
|
|
|
|
KeyProvInfo.pwszContainerName = aapWContainerName.Get();
|
|
KeyProvInfo.pwszProvName = aapWProvName.Get();
|
|
KeyProvInfo.dwProvType = PROV_RSA_FULL;
|
|
KeyProvInfo.dwFlags = 0;
|
|
KeyProvInfo.cProvParam = 0;
|
|
KeyProvInfo.rgProvParam = NULL;
|
|
KeyProvInfo.dwKeySpec = dwKeySpec;
|
|
|
|
BOOL ok = CertSetCertificateContextProperty(pCertContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
0, (void *)&KeyProvInfo);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
// Set a friendly name. If it is not specified, try to derive one
|
|
|
|
string strFN;
|
|
if(strFriendlyName.size())
|
|
strFN = strFriendlyName;
|
|
else
|
|
strFN = FriendlyName(strCert);
|
|
|
|
if(strFN.size()) {
|
|
scu::AutoArrayPtr<WCHAR> aapWFriendlyName = ToWideChar(strFN);
|
|
|
|
CRYPT_DATA_BLOB DataBlob;
|
|
|
|
DataBlob.pbData = (BYTE*)aapWFriendlyName.Get();
|
|
DataBlob.cbData = (wcslen(aapWFriendlyName.Get())+1)*sizeof(WCHAR);
|
|
ok = CertSetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID,0,&DataBlob);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
}
|
|
|
|
// Store the certificate
|
|
|
|
ok = CertAddCertificateContextToStore(m_hCertStore, pCertContext,
|
|
CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
}
|
|
|
|
|
|
void CWinRegCertStore::StoreCACert(string const &strCert, string const &strFriendlyName)
|
|
{
|
|
|
|
// Create cert context
|
|
|
|
PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING,(BYTE*)strCert.c_str(),strCert.size());
|
|
if(!pCertContext)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
// Set the different Enhanced Key usage flags. On one side, one could be
|
|
// more conservative and set fewer flags, after all the user may set
|
|
// these afterwards. On the other side, most users will not know how to
|
|
// to that and if the attributes are not set, various signature verifications
|
|
// will fail..... The four below are quite common.
|
|
|
|
BOOL ok;
|
|
CRYPT_DATA_BLOB DataBlob;
|
|
|
|
CERT_ENHKEY_USAGE EnKeyUsage;
|
|
|
|
LPSTR UsageOIDs[4];
|
|
UsageOIDs[0] = szOID_PKIX_KP_SERVER_AUTH;
|
|
UsageOIDs[1] = szOID_PKIX_KP_CLIENT_AUTH;
|
|
UsageOIDs[2] = szOID_PKIX_KP_CODE_SIGNING;
|
|
UsageOIDs[3] = szOID_PKIX_KP_EMAIL_PROTECTION;
|
|
|
|
EnKeyUsage.rgpszUsageIdentifier = UsageOIDs;
|
|
EnKeyUsage.cUsageIdentifier = sizeof(UsageOIDs)/sizeof(*UsageOIDs);
|
|
|
|
DWORD cbEncoded;
|
|
|
|
// First call to find size for memory allocation
|
|
|
|
ok = CryptEncodeObject(CRYPT_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &EnKeyUsage,NULL, &cbEncoded);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
scu::AutoArrayPtr<BYTE> aapEncoded(new BYTE[cbEncoded]);
|
|
ok = CryptEncodeObject(CRYPT_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &EnKeyUsage,aapEncoded.Get(), &cbEncoded);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
DataBlob.pbData = aapEncoded.Get();
|
|
DataBlob.cbData = cbEncoded;
|
|
|
|
ok = CertSetCertificateContextProperty(pCertContext, CERT_ENHKEY_USAGE_PROP_ID,0,&DataBlob);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
// Set a friendly name. If it is not specified, try to derive one
|
|
|
|
string strFN;
|
|
if(strFriendlyName.size())
|
|
strFN = strFriendlyName;
|
|
else
|
|
strFN = FriendlyName(strCert);
|
|
|
|
if(strFN.size()) {
|
|
scu::AutoArrayPtr<WCHAR> aapWFriendlyName = ToWideChar(strFN);
|
|
|
|
CRYPT_DATA_BLOB DataBlob;
|
|
|
|
DataBlob.pbData = (BYTE*)aapWFriendlyName.Get();
|
|
DataBlob.cbData = (wcslen(aapWFriendlyName.Get())+1)*sizeof(WCHAR);
|
|
ok = CertSetCertificateContextProperty(pCertContext,
|
|
CERT_FRIENDLY_NAME_PROP_ID,0,&DataBlob);
|
|
if(!ok)
|
|
throw scu::OsException(GetLastError());
|
|
}
|
|
|
|
// Store the certificate
|
|
|
|
ok = CertAddCertificateContextToStore(m_hCertStore, pCertContext,
|
|
CERT_STORE_ADD_NEW, NULL);
|
|
if(!ok)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if(err!=CRYPT_E_EXISTS)
|
|
throw scu::OsException(GetLastError());
|
|
}
|
|
|
|
}
|
|
|
|
scu::AutoArrayPtr<WCHAR> CWinRegCertStore::ToWideChar(string const strChar)
|
|
{
|
|
|
|
int nwc = MultiByteToWideChar(CP_ACP, NULL, strChar.c_str(),-1, 0, 0);
|
|
if (0 == nwc)
|
|
throw scu::OsException(GetLastError());
|
|
|
|
scu::AutoArrayPtr<WCHAR> aapWChar(new WCHAR[nwc]);
|
|
if (0 == MultiByteToWideChar(CP_ACP, NULL, strChar.c_str(),
|
|
-1, aapWChar.Get(), nwc))
|
|
throw scu::OsException(GetLastError());
|
|
|
|
return aapWChar;
|
|
|
|
}
|
|
|
|
string CWinRegCertStore::FriendlyName(string const CertValue)
|
|
{
|
|
|
|
string strFriendlyName;
|
|
|
|
// Derive a friendly name for the certificate
|
|
|
|
try
|
|
{
|
|
|
|
bool IsCACert = false;
|
|
|
|
X509Cert X509CertObject(CertValue);
|
|
|
|
try
|
|
{
|
|
unsigned long KeyUsage = X509CertObject.KeyUsage();
|
|
if(KeyUsage & (keyCertSign | cRLSign)) IsCACert = true;
|
|
}
|
|
catch (...) {};
|
|
|
|
if(IsCACert)
|
|
{
|
|
vector<string> orglist = X509CertObject.IssuerOrg();
|
|
if(orglist.size()>0)
|
|
strFriendlyName = orglist[0];
|
|
}
|
|
else
|
|
{
|
|
vector<string> cnlist = X509CertObject.SubjectCommonName();
|
|
if(cnlist.size()>0)
|
|
strFriendlyName = cnlist[0] + "'s ";
|
|
|
|
vector<string> orglist = X509CertObject.IssuerOrg();
|
|
if(orglist.size()>0)
|
|
strFriendlyName += orglist[0] + " ";
|
|
|
|
strFriendlyName += "ID";
|
|
}
|
|
}
|
|
catch (...) {};
|
|
|
|
return strFriendlyName;
|
|
|
|
}
|