|
|
|
date: Wed, 10 Sep 2008 02:57:01 -0700,
group: microsoft.public.platformsdk.security
back
RE: How to import certificate and PrK from PFX file to smart card
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
date: Tue, 23 Sep 2008 06:50:08 -0700
author: Ondrej P.
|
|