RE: How to import certificate and PrK from PFX file to smart card
- From: Ondrej P. <OndrejP@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Tue, 23 Sep 2008 06:50:08 -0700
Thank you for your advice.
It really did help and I've moved a fair bit, but I've still got some
problems...
Even though my code runs without errors, it doesn't write the certificate
and key to the smart card.
Here is the source code:
----------------------------------
void MyClassDlg::importCertKeyToSmartCard(CString cardPIN, _CRYPTOAPI_BLOB
&pkcs12data, CString password)
{
HCERTSTORE hCS;
hCS = PFXImportCertStore(&pkcs12data, (LPCWSTR) password, CRYPT_EXPORTABLE
| CRYPT_USER_KEYSET );
if(hCS == NULL)
{
return;
}
PCCERT_CONTEXT pCC(NULL);
PBYTE pData(NULL);
DWORD sizeOfData(0);
BOOL success;
BOOL callerFree;
CRYPT_KEY_PROV_INFO* pKeyProvInfo(NULL);
HCRYPTPROV cryptoProvider(0), cardCryptoProvider(0);
DWORD cryptAcquireCertificatePrivateKeyFlags = AT_KEYEXCHANGE;
HCRYPTKEY cryptKeyHandle(0);
HCRYPTKEY sessionKeyHandle(0);
HCRYPTKEY importedKey(0);
BYTE* pPk(NULL);
DWORD pkSize;
DWORD err;
CString readerName = m_readers[m_cbReaders.GetCurSel()]->description;
if(readerName.GetLength() > 0) {
readerName.SetAt(readerName.GetLength()-1, ' ' );
readerName.TrimRight();
}
CString containerName(L"MyContainer");
CString containerNameFull;
containerNameFull.Format(L"\\\\.\\%s\\%s", readerName, containerName);
success = CryptAcquireContextW(&cardCryptoProvider,
(LPCTSTR)containerNameFull, L"Siemens Card API
CSP", PROV_RSA_FULL,CRYPT_NEWKEYSET// | CRYPT_SILENT );
if(!success) {
return;
}
// log in using PIN
char* pin;
long pinBufferLength = cardPIN.GetLength()+1;
pin = new char[pinBufferLength];
WideCharToMultiByte(GetACP(), 0, cardPIN, pinBufferLength-1, pin,
pinBufferLength, 0, 0);
pin[pinBufferLength-1] = 0;
success = CryptSetProvParam(cardCryptoProvider, PP_KEYEXCHANGE_PIN,
(BYTE*)pin, 0);
if(!success){
err = GetLastError();
return;
}
delete [] pin;
do
{
pCC = CertEnumCertificatesInStore(hCS, pCC);
if(pCC == NULL)
{
break;
}
CertGetCertificateContextProperty(pCC, CERT_KEY_PROV_INFO_PROP_ID, NULL,
&sizeOfData);
pData = new BYTE[sizeOfData];
success = CertGetCertificateContextProperty(pCC,
CERT_KEY_PROV_INFO_PROP_ID, (PVOID)pData, &sizeOfData);
if(!success) {
err = GetLastError();
break;
}
pKeyProvInfo = (CRYPT_KEY_PROV_INFO*) pData;
success = CryptAcquireCertificatePrivateKey(pCC,CRYPT_ACQUIRE_SILENT_FLAG,
NULL, &cryptoProvider, &cryptAcquireCertificatePrivateKeyFlags, &callerFree);
if(!success) {
err = GetLastError();
break;
}
success = CryptGetUserKey(cryptoProvider, AT_KEYEXCHANGE, &cryptKeyHandle);
if(!success){
err = GetLastError();
break;
}
// export key
success = CryptGenKey(cryptoProvider, CALG_3DES, CRYPT_EXPORTABLE,
&sessionKeyHandle);
if(!success){
err = GetLastError();
break;
}
CryptExportKey(cryptKeyHandle, sessionKeyHandle, PRIVATEKEYBLOB, 0, NULL,
&pkSize );
pPk = new BYTE[pkSize];
success = CryptExportKey(cryptKeyHandle, NULL, PRIVATEKEYBLOB, 0, pPk,
&pkSize );
if(!success){
err = GetLastError();
break;
}
// import key
success = CryptImportKey(cardCryptoProvider, pPk, pkSize,
sessionKeyHandle, 0, &importedKey);
if(!success){
err = GetLastError();
break;
}
// import certificate
success = CryptSetKeyParam(importedKey, KP_CERTIFICATE,
pCC->pbCertEncoded, 0);
if(!success){
err = GetLastError();
break;
}
}
while(false);
if(pCC) {
CertFreeCertificateContext(pCC);
}
if(pData) {
delete [] pData;
pData = NULL;
}
if(pPk) {
memset(pPk, 0, pkSize);
delete [] pPk;
pPk = NULL;
}
if(importedKey) {
CryptDestroyKey(importedKey);
}
if(cryptKeyHandle) {
CryptDestroyKey(cryptKeyHandle);
}
if(callerFree && cryptoProvider) {
CryptReleaseContext(cryptoProvider, NULL);
}
}
----------------------------------
"Mounir IDRASSI" wrote:
Hi,
Once you have the HCERTSTORE returned by PFXImportCertStore, you must
enumerate all the certificates on this store using
CertEnumCertificatesInStore. For each certificate found, do the following :
- Retrieve its CERT_KEY_PROV_INFO_PROP_ID property using
CertGetCertificateContextProperty. If it doesn't exists, then this is
certainly a standalone certificate with no associated key ( a root
certificate for example)
- Using the information from the property mentioned above, call the
function CryptAcquireCertificatePrivateKey to get a handle on the CSP context
of the key associated with this certificate.
- Call CryptGetUserKey to get a handle on the private key.
- Call CryptExportKey to export the private key as a PRIVATEKEYBLOB blob.
- Here you have all the needed information to import the certificate and
its private key into the smart card. You can for example create a new
container on the card using CryptAcquireContext , then import the private key
using CryptImportKey and finally put the certificate in the card by setting
the KP_CERTIFICATE property on the key you have just created.
I hope the above steps are clear enough to help you in what you intend to do.
Cheers,
--
Mounir IDRASSI
IDRIX
http://www.idrix.fr
.
- Follow-Ups:
- References:
- How to import certificate and PrK from PFX file to smart card
- From: Ondrej P.
- RE: How to import certificate and PrK from PFX file to smart card
- From: Mounir IDRASSI
- How to import certificate and PrK from PFX file to smart card
- Prev by Date: Re: Vista and signing certificate on smart card
- Next by Date: How to retrieve list of group memberships from a username SID.
- Previous by thread: RE: How to import certificate and PrK from PFX file to smart card
- Next by thread: RE: How to import certificate and PrK from PFX file to smart card
- Index(es):
Relevant Pages
|