/** The verbosity level. */ static unsigned g_cVerbosityLevel = 1; static const char *errorToString(DWORD dwErr) { switch (dwErr) { #define MY_CASE(a_uConst) case a_uConst: return #a_uConst; MY_CASE(CRYPT_E_MSG_ERROR); MY_CASE(CRYPT_E_UNKNOWN_ALGO); MY_CASE(CRYPT_E_OID_FORMAT); MY_CASE(CRYPT_E_INVALID_MSG_TYPE); MY_CASE(CRYPT_E_UNEXPECTED_ENCODING); MY_CASE(CRYPT_E_AUTH_ATTR_MISSING); MY_CASE(CRYPT_E_HASH_VALUE); MY_CASE(CRYPT_E_INVALID_INDEX); MY_CASE(CRYPT_E_ALREADY_DECRYPTED); MY_CASE(CRYPT_E_NOT_DECRYPTED); MY_CASE(CRYPT_E_RECIPIENT_NOT_FOUND); MY_CASE(CRYPT_E_CONTROL_TYPE); MY_CASE(CRYPT_E_ISSUER_SERIALNUMBER); MY_CASE(CRYPT_E_SIGNER_NOT_FOUND); MY_CASE(CRYPT_E_ATTRIBUTES_MISSING); MY_CASE(CRYPT_E_STREAM_MSG_NOT_READY); MY_CASE(CRYPT_E_STREAM_INSUFFICIENT_DATA); MY_CASE(CRYPT_I_NEW_PROTECTION_REQUIRED); MY_CASE(CRYPT_E_BAD_LEN); MY_CASE(CRYPT_E_BAD_ENCODE); MY_CASE(CRYPT_E_FILE_ERROR); MY_CASE(CRYPT_E_NOT_FOUND); MY_CASE(CRYPT_E_EXISTS); MY_CASE(CRYPT_E_NO_PROVIDER); MY_CASE(CRYPT_E_SELF_SIGNED); MY_CASE(CRYPT_E_DELETED_PREV); MY_CASE(CRYPT_E_NO_MATCH); MY_CASE(CRYPT_E_UNEXPECTED_MSG_TYPE); MY_CASE(CRYPT_E_NO_KEY_PROPERTY); MY_CASE(CRYPT_E_NO_DECRYPT_CERT); MY_CASE(CRYPT_E_BAD_MSG); MY_CASE(CRYPT_E_NO_SIGNER); MY_CASE(CRYPT_E_PENDING_CLOSE); MY_CASE(CRYPT_E_REVOKED); MY_CASE(CRYPT_E_NO_REVOCATION_DLL); MY_CASE(CRYPT_E_NO_REVOCATION_CHECK); MY_CASE(CRYPT_E_REVOCATION_OFFLINE); MY_CASE(CRYPT_E_NOT_IN_REVOCATION_DATABASE); MY_CASE(CRYPT_E_INVALID_NUMERIC_STRING); MY_CASE(CRYPT_E_INVALID_PRINTABLE_STRING); MY_CASE(CRYPT_E_INVALID_IA5_STRING); MY_CASE(CRYPT_E_INVALID_X500_STRING); MY_CASE(CRYPT_E_NOT_CHAR_STRING); MY_CASE(CRYPT_E_FILERESIZED); MY_CASE(CRYPT_E_SECURITY_SETTINGS); MY_CASE(CRYPT_E_NO_VERIFY_USAGE_DLL); MY_CASE(CRYPT_E_NO_VERIFY_USAGE_CHECK); MY_CASE(CRYPT_E_VERIFY_USAGE_OFFLINE); MY_CASE(CRYPT_E_NOT_IN_CTL); MY_CASE(CRYPT_E_NO_TRUSTED_SIGNER); MY_CASE(CRYPT_E_MISSING_PUBKEY_PARA); MY_CASE(CRYPT_E_OSS_ERROR); default: { PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr); if (pWinComMsg) return pWinComMsg->pszDefine; static char s_szErr[32]; RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr); return s_szErr; } } } #if 0 /* hacking */ static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore) { /* * Open the source. */ void *pvFile; size_t cbFile; int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc); RTEXITCODE rcExit = RTEXITCODE_FAILURE; PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (PBYTE)pvFile, (DWORD)cbFile); if (pCertCtx) { /* * Open the destination. */ HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL /* hCryptProv = default */, /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, pwszStore); if (hDstStore != NULL) { #if 0 DWORD dwContextType; if (CertAddSerializedElementToStore(hDstStore, pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded, CERT_STORE_ADD_NEW, 0 /* dwFlags (reserved) */, CERT_STORE_ALL_CONTEXT_FLAG, &dwContextType, NULL)) { RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType); rcExit = RTEXITCODE_SUCCESS; } else RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError())); #else if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL)) { RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore); rcExit = RTEXITCODE_SUCCESS; } else RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError())); #endif CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG); } else RTMsgError("CertOpenStore returned %s", errorToString(GetLastError())); CertFreeCertificateContext(pCertCtx); } else RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError())); RTFileReadAllFree(pvFile, cbFile); return rcExit; #if 0 CRYPT_DATA_BLOB Blob; Blob.cbData = (DWORD)cbData; Blob.pbData = (PBYTE)pvData; HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", ) #endif }
/***************************************************************************** wmain *****************************************************************************/ DWORD __cdecl wmain( int argc, LPWSTR argv[] ) { HRESULT hr = S_OK; HCERTSTORE hStore = NULL; PCCERT_CHAIN_CONTEXT *prgpSelection = 0; DWORD cSelection = 0; BYTE bDigSig = CERT_DIGITAL_SIGNATURE_KEY_USAGE; // in byte 0 ULONG ulAuthPackage; BOOL bSave = FALSE; DWORD cbAuthBuffer = 0; DWORD dwError = ERROR_SUCCESS; DWORD dwAuthError = 0; void * pBuffer = NULL; ULONG ulSize = 0; LPVOID pbAuthBuffer; PCCERT_CONTEXT pCertContext = NULL; CREDUI_INFO CredUiInfo; CredUiInfo.pszCaptionText = L"Select your credentials"; CredUiInfo.pszMessageText = L"Please select a certificate"; CredUiInfo.cbSize = sizeof(CredUiInfo); CredUiInfo.hbmBanner = NULL; CredUiInfo.hwndParent = NULL; ulAuthPackage = (ULONG) CERT_CREDENTIAL_PROVIDER_ID; CERT_SELECTUI_INPUT certInput = {0}; void* rgParaEKU[] = { szOID_PKIX_KP_EMAIL_PROTECTION }; CERT_SELECT_CRITERIA EKUCriteria = { CERT_SELECT_BY_ENHKEY_USAGE, ARRAYSIZE(rgParaEKU), rgParaEKU }; CERT_EXTENSION extDigSig = { NULL, // pszObjId FALSE, // fCritical {1, &bDigSig} // Value }; void* rgParaKU[] = { &extDigSig // digital signature key usage }; CERT_SELECT_CRITERIA KUCriteria = { CERT_SELECT_BY_KEY_USAGE, ARRAYSIZE(rgParaKU), rgParaKU }; CERT_SELECT_CRITERIA rgCriteriaFilter[] = { EKUCriteria, KUCriteria }; hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY" ); if( NULL == hStore ) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } wprintf( L"Looking for certificates in MY store ...\n" ); if( !CertSelectCertificateChains( NULL, CERT_SELECT_TRUSTED_ROOT | CERT_SELECT_HAS_PRIVATE_KEY, NULL, ARRAYSIZE(rgCriteriaFilter), rgCriteriaFilter, hStore, &cSelection, &prgpSelection)) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto CleanUp; } if( cSelection < 1 ) { wprintf( L"No certificates found matching the selection criteria.\n" ); goto CleanUp; } wprintf( L"%u certificates found matching the selection criteria.\n", cSelection ); // // show the selected cert in UI // certInput.prgpChain = prgpSelection; certInput.cChain = cSelection; hr = CertSelectionGetSerializedBlob( &certInput, &pBuffer, &ulSize); if(S_OK != hr) goto CleanUp; dwError = CredUIPromptForWindowsCredentials( &CredUiInfo, dwAuthError, (PULONG)&ulAuthPackage, pBuffer, ulSize, &pbAuthBuffer, &cbAuthBuffer, &bSave, CREDUIWIN_AUTHPACKAGE_ONLY); if(ERROR_SUCCESS != dwError) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { //get the selected cert context if( !CertAddSerializedElementToStore( NULL, (BYTE *)pbAuthBuffer, cbAuthBuffer, CERT_STORE_ADD_ALWAYS, 0, // flags CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, reinterpret_cast<const void **>(&pCertContext) )) { goto CleanUp; } // // pCertContext now is ready to use // } CleanUp: if( FAILED( hr )) { ReportError( NULL, hr ); } if( NULL != pBuffer ) { LocalFree(pBuffer); } if( NULL != pCertContext ) { CertFreeCertificateContext(pCertContext); } return (DWORD)hr; UNREFERENCED_PARAMETER( argc ); UNREFERENCED_PARAMETER( argv ); }