//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1996 - 2001 // // File: scinfo.cpp // // Abstract: // // This application is used to provide a snapshot of the Calais (Smart Card // Resource Manager) service's status, and to display certificates on smart // cards via the common WinNT UI. // // SCInfo -- describes the RM status and displays each available sc cert(s) // // The following options are always enabled: // Readername -- for just one reader // -sig -- display signature key certs only // -ex -- display exchange key certs only // -nocert -- don't look for certs to display // -key -- verify keyset public key matches cert public key // // Author: Amanda Matlosz (AMatlosz) 07/14/1998 // // Environment: Win32 Console App // // Notes: For use in NT5 public key rollout testing // // Need to include the following libs: // winscard.lib // //-------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include "cscsp.h" #define __dwFILE__ __dwFILE_CERTUTIL_SCINFO_CPP__ #define wszSCARDSERVICE L"SCardSvr" //+------------------------------------------------------------------------- // IsSCardSvrRunning checks the registry and queries the service for status //-------------------------------------------------------------------------- HRESULT IsSCardSvrRunning() { HRESULT hr; WCHAR const *pwszError = NULL; UINT idmsg = IDS_SMARTCARD_NOTRUNNING; // "The Microsoft Smart Card Resource Manager is not running." HANDLE hSCardSvrStarted = NULL; HMODULE hDll = GetModuleHandle(L"winscard.dll"); typedef HANDLE (WINAPI FNSCARDACCESSSTARTEDEVENT)(VOID); FNSCARDACCESSSTARTEDEVENT *pfnSCardAccessStartedEvent; pfnSCardAccessStartedEvent = (FNSCARDACCESSSTARTEDEVENT *) GetProcAddress(hDll, "SCardAccessStartedEvent"); if (NULL == pfnSCardAccessStartedEvent) { hr = myHLastError(); pwszError = L"GetProcAddress"; _JumpErrorStr(hr, error, "GetProcAddress", L"SCardAccessStartedEvent"); } hSCardSvrStarted = (*pfnSCardAccessStartedEvent)(); if (NULL == hSCardSvrStarted) { hr = myHLastError(); if (S_OK == hr) { hr = E_HANDLE; } pwszError = L"SCardAccessStartedEvent"; _JumpError(hr, error, "SCardAccessStartedEvent"); } hr = WaitForSingleObject(hSCardSvrStarted, 1000); if (WAIT_OBJECT_0 != hr) { hr = myHError(hr); pwszError = L"WaitForSingleObject"; _JumpError(hr, error, "WaitForSingleObject"); } idmsg = IDS_SMARTCARD_RUNNING; // "The Microsoft Smart Card Resource Manager is running." hr = S_OK; error: // Display status wprintf(myLoadResourceString(idmsg)); wprintf(wszNewLine); if (S_OK != hr) { // IDS_SERVICEPAUSED; // "Service is paused." // IDS_SERVICESTOPPED; // "Service is stopped." cuPrintErrorAndString( pwszError, IDS_SERVICEUNKNOWNSTATE, // "Service is in an unknown state." hr, NULL); } return(hr); } VOID FreeReaderList( IN SCARDCONTEXT hSCard, IN WCHAR *pwszzReaderNameAlloc, IN SCARD_READERSTATE *prgReaderState) { if (NULL != hSCard) { if (NULL != pwszzReaderNameAlloc) { SCardFreeMemory(hSCard, pwszzReaderNameAlloc); } SCardReleaseContext(hSCard); } if (NULL != prgReaderState) { LocalFree(prgReaderState); } } //+------------------------------------------------------------------------- // BuildReaderList tries to set *phSCard and get a list of currently available // smart card readers. //-------------------------------------------------------------------------- HRESULT BuildReaderList( OPTIONAL IN WCHAR const *pwszReaderName, OUT SCARDCONTEXT *phSCard, OUT WCHAR **ppwszzReaderNameAlloc, OUT SCARD_READERSTATE **pprgReaderState, OUT DWORD *pcReaders) { HRESULT hr; DWORD i; DWORD dwAutoAllocate; SCARDCONTEXT hSCard = NULL; WCHAR *pwszzReaderNameAlloc = NULL; SCARD_READERSTATE *prgReaderState = NULL; DWORD cReaders; *phSCard = NULL; *ppwszzReaderNameAlloc = NULL; *pcReaders = 0; *pprgReaderState = NULL; wprintf(myLoadResourceString(IDS_SCREADER_STATUS_COLON)); wprintf(wszNewLine); // Acquire global SCARDCONTEXT from resource manager if possible hr = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSCard); if (S_OK != hr) { cuPrintAPIError(L"SCardEstablishContext", hr); wprintf(myLoadResourceString(IDS_SC_USER_SCOPE)); wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_SC_NO_LIST)); wprintf(wszNewLine); _JumpError(hr, error, "SCardEstablishContext"); } // Build a readerstatus array from either a list of readers; or use the one // the user specified cReaders = 1; if (NULL == pwszReaderName) { dwAutoAllocate = SCARD_AUTOALLOCATE; hr = SCardListReaders( hSCard, SCARD_DEFAULT_READERS, (WCHAR *) &pwszzReaderNameAlloc, &dwAutoAllocate); if (S_OK != hr) { cuPrintAPIError(L"SCardListReaders", hr); wprintf(myLoadResourceString(IDS_SC_LIST_FAILED)); wprintf(wszNewLine); if (SCARD_E_NO_READERS_AVAILABLE == hr) { wprintf(myLoadResourceString(IDS_SC_LIST_FAILED_NO_READERS)); } else { wprintf(myLoadResourceString(IDS_SC_LIST_FAILED_GENERIC)); } wprintf(wszNewLine); _JumpError(hr, error, "SCardListReaders"); } // Build a readerstatus array... cReaders = 0; if (NULL != pwszzReaderNameAlloc) { for ( pwszReaderName = pwszzReaderNameAlloc; L'\0' != *pwszReaderName; pwszReaderName += wcslen(pwszReaderName) + 1) { cReaders++; } } pwszReaderName = pwszzReaderNameAlloc; } prgReaderState = (SCARD_READERSTATE *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, cReaders * sizeof(**pprgReaderState)); if (NULL == prgReaderState) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } wprintf(myLoadResourceString(IDS_SC_READERS_COLON)); wprintf(L" %u\n", cReaders); for (i = 0; i < cReaders; i++) { wprintf(L" %u: %ws\n", i, pwszReaderName); prgReaderState[i].szReader = const_cast(pwszReaderName); prgReaderState[i].dwCurrentState = SCARD_STATE_UNAWARE; pwszReaderName += wcslen(pwszReaderName) + 1; } // ...And get the reader status from the resource manager hr = SCardGetStatusChange( hSCard, INFINITE, // hardly prgReaderState, cReaders); if (S_OK != hr) { cuPrintAPIError(L"SCardGetStatusChange", hr); _JumpError(hr, error, "SCardGetStatusChange"); } *phSCard = hSCard; hSCard = NULL; *ppwszzReaderNameAlloc = pwszzReaderNameAlloc; pwszzReaderNameAlloc = NULL; *pprgReaderState = prgReaderState; prgReaderState = NULL; *pcReaders = cReaders; hr = S_OK; error: FreeReaderList(hSCard, pwszzReaderNameAlloc, prgReaderState); return(hr); } //+------------------------------------------------------------------------- // DisplayReaderList displays the status for a list of readers. //-------------------------------------------------------------------------- HRESULT DisplayReaderList( IN SCARDCONTEXT hSCard, IN SCARD_READERSTATE const *prgReaderState, IN DWORD cReaders) { HRESULT hr; DWORD i; DWORD dwAutoAllocate; UINT idsMsg; // Display all reader information for (i = 0; i < cReaders; i++) { DWORD dwState; WCHAR const *pwszSep; static WCHAR const s_wszSep[] = L" | "; //--- reader: readerName wprintf(myLoadResourceString(IDS_SC_MINUS_READER_COLON)); wprintf(L" %ws\n", prgReaderState[i].szReader); //--- status: /bits/ wprintf(myLoadResourceString(IDS_SC_MINUS_STATUS_COLON)); dwState = prgReaderState[i].dwEventState; pwszSep = L" "; if (SCARD_STATE_UNKNOWN & dwState) { wprintf(L"%wsSCARD_STATE_UNKNOWN", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_UNAVAILABLE & dwState) { wprintf(L"%wsSCARD_STATE_UNAVAILABLE", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_EMPTY & dwState) { wprintf(L"%wsSCARD_STATE_EMPTY", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_PRESENT & dwState) { wprintf(L"%wsSCARD_STATE_PRESENT", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_EXCLUSIVE & dwState) { wprintf(L"%wsSCARD_STATE_EXCLUSIVE", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_INUSE & dwState) { wprintf(L"%wsSCARD_STATE_INUSE", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_MUTE & dwState) { wprintf(L"%wsSCARD_STATE_MUTE", pwszSep); pwszSep = s_wszSep; } if (SCARD_STATE_UNPOWERED & dwState) { wprintf(L"%wsSCARD_STATE_UNPOWERED", pwszSep); } wprintf(wszNewLine); //--- status: what scstatus would say // NO CARD if (SCARD_STATE_EMPTY & dwState) // SC_STATUS_NO_CARD { idsMsg = IDS_SC_STATUS_NO_CARD; } // CARD in reader: SHARED, EXCLUSIVE, FREE, UNKNOWN ? else if (SCARD_STATE_PRESENT & dwState) { if (SCARD_STATE_MUTE & dwState) // SC_STATUS_UNKNOWN { idsMsg = IDS_SC_STATUS_UNKNOWN; } else if (SCARD_STATE_INUSE & dwState) { if (dwState & SCARD_STATE_EXCLUSIVE & dwState) { // SC_STATUS_EXCLUSIVE idsMsg = IDS_SC_STATUS_BUSY; } else // SC_STATUS_SHARED { idsMsg = IDS_SC_STATUS_SHARED; } } else // SC_SATATUS_AVAILABLE { idsMsg = IDS_SC_STATUS_AVAILABLE; } } // READER ERROR: at this point, something's gone wrong else // SCARD_STATE_UNAVAILABLE & dwState -- SC_STATUS_ERROR { idsMsg = IDS_SC_STATUS_NO_RESPONSE; } wprintf(myLoadResourceString(IDS_SC_MINUS_STATUS_COLON)); wprintf(L" "); wprintf(myLoadResourceString(idsMsg)); wprintf(wszNewLine); // card name(s): wprintf(myLoadResourceString(IDS_SC_MINUS_CARD_COLON)); if (0 < prgReaderState[i].cbAtr) { WCHAR *pwszCardName = NULL; // Get the name of the card dwAutoAllocate = SCARD_AUTOALLOCATE; hr = SCardListCards( hSCard, prgReaderState[i].rgbAtr, NULL, 0, (WCHAR *) &pwszCardName, &dwAutoAllocate); if (S_OK != hr || NULL == pwszCardName) { wprintf(L" "); wprintf(myLoadResourceString(IDS_SC_UNKNOWN_CARD)); } else { WCHAR const *pwszName; pwszSep = L""; for ( pwszName = pwszCardName; L'\0' != *pwszName; pwszName += wcslen(pwszName) + 1) { wprintf(L"%ws %ws", pwszSep, pwszName); pwszSep = L","; } } if (NULL != pwszCardName) { SCardFreeMemory(hSCard, pwszCardName); } } wprintf(wszNewLine); } hr = S_OK; //error: return(hr); } HRESULT myCryptGetProvParamToUnicode( IN HCRYPTPROV hProv, IN DWORD dwParam, OUT WCHAR **ppwszOut, IN DWORD dwFlags) { HRESULT hr; char *psz = NULL; DWORD cb; *ppwszOut = NULL; if (!CryptGetProvParam(hProv, dwParam, NULL, &cb, 0)) { hr = myHLastError(); _JumpError(hr, error, "CryptGetProvParam"); } psz = (char *) LocalAlloc(LMEM_FIXED, cb); if (NULL == psz) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } if (!CryptGetProvParam(hProv, dwParam, (BYTE *) psz, &cb, 0)) { hr = myHLastError(); _JumpError(hr, error, "CryptGetProvParam"); } if (!myConvertSzToWsz(ppwszOut, psz, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "myConvertSzToWsz"); } hr = S_OK; error: if (NULL != psz) { LocalFree(psz); } return(hr); } //+------------------------------------------------------------------------- // GetCertContext -- called by DisplayCerts //-------------------------------------------------------------------------- HRESULT GetCertContext( IN HCRYPTPROV hProv, IN HCRYPTKEY hKey, IN DWORD dwKeySpec, IN WCHAR const *pwszKeyType, OUT CERT_CONTEXT const **ppCert) { HRESULT hr; CERT_CONTEXT const *pCert = NULL; CERT_PUBLIC_KEY_INFO *pKey = NULL; CRYPT_KEY_PROV_INFO KeyProvInfo; WCHAR *pwszContainerName = NULL; WCHAR *pwszProvName = NULL; BYTE *pbCert = NULL; DWORD cbCert; DWORD cbKey; *ppCert = NULL; // Get the cert from this key if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &cbCert, 0)) { hr = myHLastError(); if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { _JumpError(hr, error, "CryptGetKeyParam"); } } pbCert = (BYTE *) LocalAlloc(LMEM_FIXED, cbCert); if (NULL == pbCert) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCert, &cbCert, 0)) { hr = myHLastError(); _JumpError(hr, error, "CryptGetKeyParam"); } // Convert the certificate into a Cert Context. pCert = CertCreateCertificateContext( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbCert, cbCert); if (NULL == pCert) { hr = myHLastError(); _JumpError(hr, error, "CertCreateCertificateContext"); } // Perform public key check wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_FORMAT_SC_TESTING_MATCH), pwszKeyType); wprintf(wszNewLine); if (!CryptExportPublicKeyInfo( hProv, dwKeySpec, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, &cbKey)) // in, out { hr = myHLastError(); cuPrintAPIError(L"CryptExportPublicKeyInfo", hr); _JumpError(hr, error, "CryptExportPublicKeyInfo"); } if (0 == cbKey) { hr = SCARD_E_UNEXPECTED; // huh? wprintf( myLoadResourceString(IDS_SC_SIZE_ZERO), L"CryptExportPublicKeyInfo"); wprintf(wszNewLine); _JumpError(hr, error, "zero info size"); } pKey = (CERT_PUBLIC_KEY_INFO *) LocalAlloc(LMEM_FIXED, cbKey); if (NULL == pKey) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } if (!CryptExportPublicKeyInfo( hProv, dwKeySpec, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pKey, &cbKey)) { hr = myHLastError(); cuPrintAPIError(L"CryptExportPublicKeyInfo", hr); _JumpError(hr, error, "CryptExportPublicKeyInfo"); } if (!CertComparePublicKeyInfo( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pKey, // from the private keyset &pCert->pCertInfo->SubjectPublicKeyInfo)) // cert public key { wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_SC_KEYPROVINFO_KEY)); wprintf(wszNewLine); cuDumpPublicKey(pKey); wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_SC_CERT_KEY)); wprintf(wszNewLine); cuDumpPublicKey(&pCert->pCertInfo->SubjectPublicKeyInfo); // by design, CertComparePublicKeyInfo doesn't set last error! hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "CertComparePublicKeyInfo"); } wprintf(myLoadResourceString(IDS_SC_KEY_MATCHES)); wprintf(wszNewLine); // Associate cryptprovider w/ the private key property of this cert // ... need the container name hr = myCryptGetProvParamToUnicode( hProv, PP_CONTAINER, &pwszContainerName, 0); _JumpIfError(hr, error, "myCryptGetProvParamToUnicode"); // ... need the provider name hr = myCryptGetProvParamToUnicode(hProv, PP_NAME, &pwszProvName, 0); _JumpIfError(hr, error, "myCryptGetProvParamToUnicode"); // Set the cert context properties to reflect the prov info KeyProvInfo.pwszContainerName = pwszContainerName; KeyProvInfo.pwszProvName = pwszProvName; KeyProvInfo.dwProvType = PROV_RSA_FULL; KeyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID; KeyProvInfo.cProvParam = 0; KeyProvInfo.rgProvParam = NULL; KeyProvInfo.dwKeySpec = dwKeySpec; if (!CertSetCertificateContextProperty( pCert, CERT_KEY_PROV_INFO_PROP_ID, 0, (VOID *) &KeyProvInfo)) { hr = myHLastError(); // the cert's been incorrectly created -- scrap it. _JumpError(hr, error, "CertSetCertificateContextProperty"); } hr = cuDumpCertKeyProviderInfo(g_wszPad2, pCert, NULL, NULL); _PrintIfError(hr, "cuDumpCertKeyProviderInfo"); if (!g_fCryptSilent) { if (AT_SIGNATURE == dwKeySpec) { hr = myValidateKeyForSigning( hProv, &pCert->pCertInfo->SubjectPublicKeyInfo, CALG_SHA1); } else { hr = myValidateKeyForEncrypting( hProv, &pCert->pCertInfo->SubjectPublicKeyInfo, CALG_RC4); } if (S_OK != hr) { if (SCARD_W_CANCELLED_BY_USER != hr) { wprintf(myLoadResourceString(IDS_ERR_PRIVATEKEY_MISMATCH)); // "ERROR: Certificate public key does NOT match private key" wprintf(wszNewLine); //_JumpError(hr, error, "myValidateKeyForEncrypting"); _PrintError(hr, "myValidateKeyForEncrypting"); } } else { wprintf(myLoadResourceString(IDS_PRIVATEKEY_VERIFIES)); wprintf(wszNewLine); } } *ppCert = pCert; pCert = NULL; hr = S_OK; error: if (NULL != pbCert) { LocalFree(pbCert); } if (NULL != pKey) { LocalFree(pKey); } if (NULL != pwszContainerName) { LocalFree(pwszContainerName); } if (NULL != pwszProvName) { LocalFree(pwszProvName); } if (NULL != pCert) { CertFreeCertificateContext(pCert); } return(hr); } //+------------------------------------------------------------------------- // DisplayChainInfo -- This code verifies that the SC cert is valid. // Uses identical code to KDC cert chaining engine. // // Author: Todds //-------------------------------------------------------------------------- DWORD DisplayChainInfo( IN CERT_CONTEXT const *pCert) { HRESULT hr; CERT_CHAIN_PARA ChainParameters; char *pszSCUsage = szOID_KP_SMARTCARD_LOGON; CERT_CHAIN_CONTEXT const *pChainContext = NULL; DWORD VerifyState; ZeroMemory(&ChainParameters, sizeof(ChainParameters)); ChainParameters.cbSize = sizeof(ChainParameters); ChainParameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND; ChainParameters.RequestedUsage.Usage.cUsageIdentifier = 1; ChainParameters.RequestedUsage.Usage.rgpszUsageIdentifier = &pszSCUsage; if (!CertGetCertificateChain( HCCE_LOCAL_MACHINE, pCert, NULL, // evaluate at current time NULL, // no additional stores &ChainParameters, CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, NULL, // reserved &pChainContext)) { hr = myHLastError(); cuPrintAPIError(L"CertGetCertificateChain", hr); _JumpError(hr, error, "CertGetCertificateChain"); } if (CERT_TRUST_NO_ERROR != pChainContext->TrustStatus.dwErrorStatus) { wprintf( L"CertGetCertificateChain(dwErrorStatus) = 0x%x\n", pChainContext->TrustStatus.dwErrorStatus); wprintf(myLoadResourceString(IDS_SC_BAD_CHAIN)); wprintf(wszNewLine); } else { wprintf(myLoadResourceString(IDS_SC_GOOD_CHAIN)); wprintf(wszNewLine); } hr = cuVerifyCertContext( pCert, // pCert NULL, // hStoreCA 1, // cApplicationPolicies &pszSCUsage, // apszApplicationPolicies 0, // cIssuancePolicies NULL, // apszIssuancePolicies TRUE, // fNTAuth &VerifyState); _JumpIfError(hr, error, "cuVerifyCertContext"); error: if (NULL != pChainContext) { CertFreeCertificateChain(pChainContext); } return(hr); } HRESULT DisplayReaderCertAndKey( IN SCARD_READERSTATE const *pReaderState, IN HCRYPTPROV hProv, IN DWORD dwKeySpec, IN WCHAR const *pwszKeyType, IN WCHAR const *pwszCardName, IN WCHAR const *pwszCSPName) { HRESULT hr; HCRYPTKEY hKey = NULL; CERT_CONTEXT const *pCert = NULL; DWORD cwc; WCHAR *pwszTitle = NULL; CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewInfo; // Get the key if (!CryptGetUserKey(hProv, dwKeySpec, &hKey)) { hr = myHLastError(); cuPrintAPIError(L"CryptGetUserKey", hr); if (NTE_NO_KEY == hr) { wprintf( myLoadResourceString(IDS_FORMAT_SC_NO_KEY_COLON), pwszKeyType); } else { wprintf( myLoadResourceString(IDS_FORMAT_SC_CANNOT_OPEN_KEY_COLON), pwszKeyType); } wprintf(L" %ws\n", pReaderState->szReader); _JumpError2(hr, error, "CryptGetUserKey", NTE_NO_KEY); } // Get the cert for this key hr = GetCertContext(hProv, hKey, dwKeySpec, pwszKeyType, &pCert); if (S_OK != hr) { wprintf( myLoadResourceString(IDS_FORMAT_SC_NO_CERT_COLON), pwszKeyType); wprintf(L" %ws\n", pReaderState->szReader); _JumpError(hr, error, "GetCertContext"); } // Attempt to build a certificate chain wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_SC_VALIDATING_CHAIN)); wprintf(wszNewLine); DisplayChainInfo(pCert); // call common UI to display Cert Context // (from cryptui.h (cryptui.dll)) if (!g_fCryptSilent) { cwc = wcslen(pReaderState->szReader) + 2 + wcslen(pwszKeyType); pwszTitle = (WCHAR *) LocalAlloc( LMEM_FIXED, (cwc + 1) * sizeof(WCHAR)); if (NULL == pwszTitle) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } swprintf( pwszTitle, L"%ws: %ws", pReaderState->szReader, pwszKeyType); ZeroMemory(&CertViewInfo, sizeof(CertViewInfo)); CertViewInfo.dwSize = sizeof(CertViewInfo); //CertViewInfo.hwndParent = NULL; CertViewInfo.szTitle = pwszTitle; CertViewInfo.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_ENABLE_REVOCATION_CHECKING; CertViewInfo.pCertContext = pCert; CryptUIDlgViewCertificate(&CertViewInfo, NULL); CertFreeCertificateContext(pCert); } wprintf( myLoadResourceString(IDS_FORMAT_SC_CERT_DISPLAYED_COLON), pwszKeyType); wprintf(L" %ws\n", pReaderState->szReader); hr = S_OK; error: if (NULL != pwszTitle) { LocalFree(pwszTitle); } if (NULL != hKey) { CryptDestroyKey(hKey); } return(hr); } HRESULT DisplayReaderCert( IN SCARDCONTEXT hSCard, IN SCARD_READERSTATE const *pReaderState) { HRESULT hr; HRESULT hr2; DWORD dwAutoAllocate; WCHAR wszFQCN[256]; HCRYPTPROV hProv = NULL; WCHAR *pwszCardName = NULL; WCHAR *pwszCSPName = NULL; if (0 >= pReaderState->cbAtr) { hr = S_OK; goto error; // no point to do any more work on this reader } // Inform user of current test wprintf(L"\n=======================================================\n"); wprintf(myLoadResourceString(IDS_SC_ANALYZING_CARD_COLON)); wprintf(L" %ws\n", pReaderState->szReader); // Get the name of the card dwAutoAllocate = SCARD_AUTOALLOCATE; hr = SCardListCards( hSCard, pReaderState->rgbAtr, NULL, // rgguidInterfaces 0, // cguidInterfaceCount (WCHAR *) &pwszCardName, // mszCards &dwAutoAllocate); // pcchCards _JumpIfError(hr, error, "SCardListCards"); dwAutoAllocate = SCARD_AUTOALLOCATE; hr = SCardGetCardTypeProviderName( hSCard, pwszCardName, SCARD_PROVIDER_CSP, (WCHAR *) &pwszCSPName, &dwAutoAllocate); if (S_OK != hr) { cuPrintAPIError(L"SCardGetCardTypeProviderName", hr); wprintf( myLoadResourceString(IDS_FORMAT_SC_CANNOT_GET_CSP), pwszCardName); _JumpError(hr, error, "SCardGetCardTypeProviderName"); } // Prepare FullyQualifiedContainerName for CryptAcquireContext call swprintf(wszFQCN, L"\\\\.\\%ws\\", pReaderState->szReader); if (!CryptAcquireContext( &hProv, wszFQCN, // default container via reader pwszCSPName, PROV_RSA_FULL, g_fCryptSilent? CRYPT_SILENT : 0)) { hr = myHLastError(); wprintf(L"%ws:\n", pReaderState->szReader); wprintf(L"%ws:\n", pwszCSPName); cuPrintAPIError(L"CryptAcquireContext", hr); _JumpError(hr, error, "SCardGetCardTypeProviderName"); } // Enumerate the keys user specified and display the certs... hr = DisplayReaderCertAndKey( pReaderState, hProv, AT_SIGNATURE, L"AT_SIGNATURE", pwszCardName, pwszCSPName); _PrintIfError2(hr, "DisplayReaderCertAndKey", NTE_NO_KEY); hr2 = DisplayReaderCertAndKey( pReaderState, hProv, AT_KEYEXCHANGE, L"AT_KEYEXCHANGE", pwszCardName, pwszCSPName); _PrintIfError2(hr2, "DisplayReaderCertAndKey", NTE_NO_KEY); if (S_OK == hr) { hr = hr2; hr2 = S_OK; } // ignore NTE_NO_KEY if the other key type exists or has a different error: if (NTE_NO_KEY == hr) { hr = hr2; _PrintIfError2(hr, "DisplayReaderCertAndKey", NTE_NO_KEY); } error: if (NULL != pwszCSPName) { SCardFreeMemory(hSCard, pwszCSPName); } if (NULL != pwszCardName) { SCardFreeMemory(hSCard, pwszCardName); } if (NULL != hProv) { CryptReleaseContext(hProv, 0); } return(hr); } //+------------------------------------------------------------------------- // DisplayCerts //-------------------------------------------------------------------------- HRESULT DisplayCerts( IN SCARDCONTEXT hSCard, IN SCARD_READERSTATE const *prgReaderState, IN DWORD cReaders) { HRESULT hr; HRESULT hr2; DWORD i; // For each reader that has a card, load the CSP and display the cert hr = S_OK; for (i = 0; i < cReaders; i++) { hr2 = DisplayReaderCert(hSCard, &prgReaderState[i]); _PrintIfError(hr2, "DisplayReaderCert"); if (S_OK == hr) { hr = hr2; } } return(hr); } //+------------------------------------------------------------------------- // verbSCInfo -- This is the main entry point for the smart card test program. // Nice and simple, borrowed from DBarlow // // Author: Doug Barlow (dbarlow) 11/10/1997 // // Revisions: // AMatlosz 2/26/98 //-------------------------------------------------------------------------- HRESULT verbSCInfo( IN WCHAR const *pwszOption, OPTIONAL IN WCHAR const *pwszReaderName, IN WCHAR const *pwszArg2, IN WCHAR const *pwszArg3, IN WCHAR const *pwszArg4) { HRESULT hr; HRESULT hr2; SCARDCONTEXT hSCard = NULL; WCHAR *pwszzReaderNameAlloc = NULL; SCARD_READERSTATE *prgReaderState = NULL; DWORD cReaders; hr = IsSCardSvrRunning(); _JumpIfError(hr, error, "IsSCardSvrRunning"); hr = BuildReaderList( pwszReaderName, &hSCard, &pwszzReaderNameAlloc, &prgReaderState, &cReaders); _PrintIfError(hr, "BuildReaderList"); hr2 = DisplayReaderList(hSCard, prgReaderState, cReaders); _PrintIfError(hr2, "DisplayReaderList"); if (S_OK == hr) { hr = hr2; } hr2 = DisplayCerts(hSCard, prgReaderState, cReaders); _PrintIfError(hr2, "DisplayCerts"); if (S_OK == hr) { hr = hr2; } wprintf(wszNewLine); wprintf(myLoadResourceString(IDS_DONE)); wprintf(wszNewLine); error: FreeReaderList(hSCard, pwszzReaderNameAlloc, prgReaderState); return(hr); }