/* 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;
}
Esempio n. 2
0
    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; 
    }