Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Smart Card : Retrieve all certificates and use CertSelectCertificate pop-up

289 views
Skip to first unread message

vinov...@gmail.com

unread,
Sep 11, 2008, 10:55:51 AM9/11/08
to

I am trying to retrieve all the certificates from the smart card which
works fine. After that, I want a pop-up asking the user to select the
certificate of their choice. For this, I use CertSelectCertificate.
The problem is the pop-up comes up but no certificates at all. Any
idea what is happening ? Any help/comment/suggestion is appreciated.

------------------- CODE BEGINS -----------------------------

// Get the default container.
BOOL bResult;
bResult = ::CryptGetProvParam (hCrypt, PP_ENUMCONTAINERS,
(BYTE*)pbData, &cbData, CRYPT_FIRST);
HCERTSTORE hArrCertStore[2]; // hold the two cert store handles.
PCCERT_CONTEXT pArrCertContext[2]; // hold the two cert contexts
int i = 0;

do
{
<String> name;
name += card->szContainerName;
name += pbData;
name += TEXT ("\\");

if (hCrypt)
::CryptReleaseContext (hCrypt, 0);

// look for the first container
bResult = ::CryptAcquireContext (&hCrypt, name.toString (),
GetProviderName (), PROV_RSA_FULL, 0);

HCRYPTKEY hKey = NULL;
DWORD dwCertLength = 0;
BYTE* bCert = NULL;

// Only the AT_KEYEXCHANGE key pair exists
::CryptGetUserKey (hCrypt , AT_KEYEXCHANGE, &hKey);

// Get the certificate length
::CryptGetKeyParam (hKey, KP_CERTIFICATE, NULL, &dwCertLength,
0);

// allocate enough memory
bCert = (BYTE*)::malloc (dwCertLength);

// Retrieve the certificate into the byte array bCert
//
::CryptGetKeyParam (hKey, KP_CERTIFICATE, bCert,
&dwCertLength, 0);

// Dispose the local copy of the key
//
if (hKey)
::CryptDestroyKey (hKey);

// create a certificate context from the byte array
PCCERT_CONTEXT pCertContext = NULL;
pCertContext = ::CertCreateCertificateContext
(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, bCert, dwCertLength);
// save the cert context.
pArrCertContext[i] = pCertContext;
// save the cert store --> is this valid ?
hArrCertStore[i] = pCertContext->hCertStore;


TCHAR szName[1000];
DWORD dwLen = sizeof (TCHAR) * 1000, dwOut;
PCERT_INFO pCertInfo = NULL;
pCertInfo = pCertContext->pCertInfo;

// get the subject details for the cert
::CertNameToStr (pCertContext->dwCertEncodingType, &pCertInfo-
>Subject, CERT_X500_NAME_STR, szName, dwLen);

// free the context
//if (pCertContext)
// ::CertFreeCertificateContext (pCertContext);

if (bCert)
{
::free (bCert);
bCert = NULL;
}
i++;
}
while (::CryptGetProvParam (hCrypt, PP_ENUMCONTAINERS,
(BYTE*)pbData, &cbData, CRYPT_NEXT) == TRUE);

// Select a certificate
//
CERT_SELECT_STRUCT pCss;

pCss.dwSize = sizeof (pCss);
pCss.hwndParent = NULL;
pCss.hInstance = NULL;
pCss.dwFlags = (DWORD)0;
pCss.pTemplateName = TEXT ("");
pCss.szPurposeOid = NULL;
pCss.szTitle = TEXT ("");
pCss.cCertStore = (DWORD)i;
pCss.cCertContext = (DWORD)i;
pCss.arrayCertStore = hArrCertStore;
pCss.arrayCertContext = pArrCertContext;
pCss.hprov = hCrypt;
pCss.pfnFilter = NULL;
pCss.szHelpFileName = TEXT ("");
pCss.pfnHook = NULL;
pCss.lCustData = NULL;

typedef BOOL (WINAPI* CSD) (PCERT_SELECT_STRUCT_A);
HMODULE hMod = ::LoadLibrary ("cryptdlg.dll");
CSD csd;
if (hMod)
{
DWORD dwErr;
csd = (CSD)::GetProcAddress (hMod, "CertSelectCertificateA");

if (csd)
{
bResult = (*csd) (&pCss); // this throws a pop-up but no
certificates displayed at all.
if (bResult != TRUE)
{
dwErr = ::GetLastError ();
}

}
::FreeLibrary (hMod);
}
------------------- CODE ENDS -----------------------------


I suspect something about the array of CertStore handles. Note, I
cannot use the CryptUIDlgSelectCertificate because the
CRYPTUI_SELECTCERTIFICATE_STRUCT looks for cert store alone and no
cert contexts. But for a smart card, a cert context help better than
the cert store handle.

Thanks.

Mounir IDRASSI

unread,
Sep 16, 2008, 8:50:01 AM9/16/08
to
Hi,

Your problem comes from the fact that you are using invalid HCERTSTORE
values for the arrayCertStore parameter of the CERT_SELECT_STRUCT. In your
code, you just copy the value of the hCertStore member of the certificate
contexte which is NULL.

In order to have the correct behavior, you must create a certificate store
in memory using CertOpenSore, add all your certificate contexts to it using
CertAddCertificateContextToStore and then point the arrayCertStore member of
CERT_SELECT_STRUCT to this handle.

I have written a small sample that perform all the necessary operations in
order to display all the certificates present on a smart card using
CertSelectCertificate. It will show you how to perform the correct steps. You
can get it at the following link :

http://www.idrix.fr/Root/Samples/ShowCertsDlg.cpp

Just replace the the CSP name by yours and run it.
I hope this will help.
Cheers,

--
Mounir IDRASSI
IDRIX
http://www.idrix.fr

To reach me: mounir_idrix_fr (replace the underscores with the at and dot
characters respectively)

0 new messages