利用OpenSSL的PKCS12_parse函数进行证书格式转换的参考代码。
目前这个函数还存在内存泄漏,这是OpenSSL 的Bug,做法上完全可以参考。
EVP_CIPHER *g_pEncAlg = NULL;
ESMTRESULT OsPEMCredConvert(FILE *fIn, char *pszP12Password, char *pszPassword, char /
*pszFilename, BOOL fMakeCertChain)
{
ESMTRESULT hr = NF_S_OK;
PKCS12 *p12 = NULL;
EVP_PKEY *pPkey = NULL;
X509 *pCert = NULL;
BIO *pBIO = NULL;
STACK_OF(X509) *pCaCerts=NULL;
char abFilename[MAXPATHLEN] = "";
FILE *fOut = NULL;
int fCerts = INFO;
NfCtx nfCtx;
nfCtx.fIn = fIn;
nfCtx.fOut = stdout;
CRYPTO_malloc_debug_init();
MemCheck_start();
do
{
if (fMakeCertChain && g_fOutputCaCerts)
{
hr = CRED_E_INCOMPATIBLE_FLAGS;
break;
}
if (fMakeCertChain)
fCerts |= CLCERTS;
else if (g_fOutputCaCerts)
fCerts |= CACERTS | NOKEYS;
if ((pBIO = BIO_new(NfBIO())) == NULL)
{
hr = CRED_E_BIO;
break;
}
BIO_ctrl(pBIO, BIO_CTRL_SET, BIO_NOCLOSE, (char *)&nfCtx);
if ((p12 = d2i_PKCS12_bio(pBIO, &p12)) == NULL)
{
hr = CRED_E_P12_OPEN;
break;
}
if (PKCS12_parse(p12, pszP12Password ? pszP12Password : "", &pPkey, &pCert, /
(STACK **)&pCaCerts) <= 0) {
hr = CRED_E_P12_PARSE;
break;
}
if (pszP12Password == NULL)
{
if (!PKCS12_verify_mac(p12, NULL, 0))
{
hr = CRED_E_P12_BAD_PWD;
break;
}
}
else if (!PKCS12_verify_mac(p12, pszP12Password, -1))
{
hr = CRED_E_P12_BAD_PWD;
break;
}
/* Encrypt private key with 3DES if required */
g_pEncAlg = pszPassword != NULL ? EVP_des_ede3_cbc() : NULL;
if (!dump_certs_keys_p12 (pBIO, p12, pszP12Password, -1, fCerts, pszPassword))
{
hr = CRED_E_P12_PARSE;
break;
}
} while (0);
if (fOut) fclose(fOut);
if (pCaCerts) sk_X509_free(pCaCerts);
if (pCert) X509_free(pCert);
if (pPkey)EVP_PKEY_free(pPkey);
if (p12) PKCS12_free(p12);
if (pBIO) BIO_free(pBIO);
ERR_free_strings();
ERR_remove_state(0);
EVP_cleanup();
MemCheck_stop();
CRYPTO_mem_leaks(stdout);
return (hr);
}