/* sqAddPfxCertToStore: Adds a PFX certificate to MY certificate store. Arguments: pfxData - the contents of the PFX certificate file pfxLen - the length of the PFX certificate file passData - the utf8 encoded password for the file passLen - the size of the password Returns: 1 on success, 0 on failure */ static sqInt sqAddPfxCertToStore(char *pfxData, sqInt pfxLen, char *passData, sqInt passLen) { PCCERT_CONTEXT pContext; HCERTSTORE pfxStore, myStore; CRYPT_DATA_BLOB blob; WCHAR widePass[4096]; /* Verify that this is a PFX file */ blob.cbData = pfxLen; blob.pbData = pfxData; if(!PFXIsPFXBlob(&blob)) return 0; /* Not a PFX blob */ /* Verify that the password is all right */ widePass[0] = 0; if(passLen > 0) { DWORD wideLen = MultiByteToWideChar(CP_UTF8, 0, passData, passLen, widePass, 4095); widePass[wideLen] = 0; } if(!PFXVerifyPassword(&blob, widePass, 0)) return 0; /* Invalid password */ /* Import the PFX blob into a temporary store */ pfxStore = PFXImportCertStore(&blob, widePass, 0); if(!pfxStore) return 0; /* And copy the certificates to MY store */ myStore = CertOpenSystemStore(0, "MY"); pContext = NULL; while(pContext = CertEnumCertificatesInStore(pfxStore, pContext)) { CertAddCertificateContextToStore(myStore, pContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL); } CertCloseStore(myStore, 0); CertCloseStore(pfxStore, 0); return 1; }
void PfxCertificate::init( ByteBuffer pfxBlob, const tstring & password, const tstring & certName) { CRYPT_DATA_BLOB blob = {0}; blob.cbData = static_cast<DWORD>(pfxBlob.getLength()); blob.pbData = (BYTE*) pfxBlob.getPtr(); BOOL recognizedPFX = PFXIsPFXBlob(&blob); DWORD dwErr = GetLastError(); RCF_VERIFY( recognizedPFX, Exception(_RcfError_ApiError("PFXIsPFXBlob()"), dwErr)); std::wstring wPassword = RCF::toWstring(password); // For Windows 98, the flag CRYPT_MACHINE_KEYSET is not valid. mPfxStore = PFXImportCertStore( &blob, wPassword.c_str(), CRYPT_MACHINE_KEYSET | CRYPT_EXPORTABLE); dwErr = GetLastError(); RCF_VERIFY( mPfxStore, Exception(_RcfError_ApiError("PFXImportCertStore()"), dwErr)); PCCERT_CONTEXT pCertStore = NULL; // Tempting to use CERT_FIND_ANY for the case where there is just a single // certificate in the PFX file. However, doing so appears to not load the // private key information. So we use CERT_FIND_SUBJECT_STR instead, and // require the certificate name to be passed in. DWORD dwFindType = CERT_FIND_SUBJECT_STR; std::wstring wCertName = RCF::toWstring(certName); const void * pvFindPara = wCertName.c_str(); pCertStore = CertFindCertificateInStore( mPfxStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pCertStore); dwErr = GetLastError(); RCF_VERIFY( pCertStore, Exception(_RcfError_ApiError("CertFindCertificateInStore()"), dwErr)); BOOL bFreeHandle; HCRYPTPROV hProv; DWORD dwKeySpec; BOOL bResult = CryptAcquireCertificatePrivateKey( pCertStore, 0, NULL, &hProv, &dwKeySpec, &bFreeHandle); dwErr = GetLastError(); RCF_VERIFY( bResult, Exception(_RcfError_ApiError("CryptAcquireCertificatePrivateKey()"), dwErr)); mpCert = pCertStore; }