int TestCryptoCertEnumCertificatesInStore(int argc, char* argv[]) { int index; DWORD status; LPTSTR pszNameString; HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCertContext = NULL; /** * System Store Locations: * http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136/ */ /** * Requires elevated rights: * hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, _T("Remote Desktop")); */ hCertStore = CertOpenSystemStore((HCRYPTPROV_LEGACY) NULL, _T("MY")); // hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_CURRENT_USER, _T("MY")); if (!hCertStore) { printf("Failed to open system store\n"); return -1; } index = 0; while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext))) { status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR)); if (!pszNameString) { printf("Unable to allocate memory\n"); return -1; } status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, status); _tprintf(_T("Certificate #%d: %s\n"), index++, pszNameString); #ifdef WITH_CRYPTUI CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, NULL, NULL, 0, NULL); #endif } if (!CertCloseStore(hCertStore, 0)) { printf("Failed to close system store\n"); return -1; } return 0; }
void ca_generate_root_ca_cert_t::generate_ca_cert_clicked(){ GIE_QT_DEF_EXCEPTION_GUARD_BEGIN stcrypt::cert_name_t cert_subject_name; #define STCRYPT_TOYCA_CP_NAME(x) { auto str = ui.x##_edit->text().toStdWString(); cert_subject_name.set_##x( std::move(str) ); } STCRYPT_TOYCA_CP_NAME(common_name); STCRYPT_TOYCA_CP_NAME(country_name); STCRYPT_TOYCA_CP_NAME(locality_name); STCRYPT_TOYCA_CP_NAME(organization_name); STCRYPT_TOYCA_CP_NAME(organization_unit_name); STCRYPT_TOYCA_CP_NAME(state_or_province_name); STCRYPT_TOYCA_CP_NAME(email_name); #undef STCRYPT_TOYCA_CP_NAME // generate key pair NCRYPT_PROV_HANDLE cng_provider=0; NCRYPT_KEY_HANDLE cng_n_key_pair=0; auto status = NCryptOpenStorageProvider(&cng_provider, CNG_STCRYPT_KEYSTORAGE, 0); STCRYPT_CHECK(!FAILED(status)); BOOST_SCOPE_EXIT((&cng_provider)) { auto const status = NCryptFreeObject (cng_provider); assert( !FAILED(status) ); } BOOST_SCOPE_EXIT_END boost::uuids::uuid const key_container_id( (boost::uuids::random_generator()()) ); auto const& key_pair_container_name = boost::lexical_cast<std::wstring>( key_container_id ); status = NCryptCreatePersistedKey(cng_provider, &cng_n_key_pair, NCNG_DSTU4145, key_pair_container_name.c_str(), AT_KEYEXCHANGE, 0/*NCRYPT_OVERWRITE_KEY_FLAG*/); STCRYPT_CHECK(!FAILED(status)); BOOST_SCOPE_EXIT((&cng_n_key_pair)) { auto const status = NCryptFreeObject (cng_n_key_pair); assert( !FAILED(status) ); } BOOST_SCOPE_EXIT_END status = NCryptFinalizeKey(cng_n_key_pair, 0); STCRYPT_CHECK(!FAILED(status)); auto const& to_be_signed_cert_blob = ms_cert::create_req_blob(cert_subject_name, cng_n_key_pair, cert_subject_name); DWORD size; STCRYPT_CHECK( CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, reinterpret_cast<BYTE const*> (to_be_signed_cert_blob.data()), to_be_signed_cert_blob.size(), CRYPT_DECODE_TO_BE_SIGNED_FLAG, 0, 0, &size) ); STCRYPT_CHECK(size!=0); std::vector<unsigned char> to_be_signed_cert_blob_combined(size); STCRYPT_CHECK( CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, reinterpret_cast<BYTE const*> (to_be_signed_cert_blob.data()), to_be_signed_cert_blob.size(), CRYPT_DECODE_TO_BE_SIGNED_FLAG, 0, to_be_signed_cert_blob_combined.data(), &size) ); to_be_signed_cert_blob_combined.resize(size); CERT_INFO* const cert_to_be_signed = static_cast<CERT_INFO*>( static_cast<void*>( to_be_signed_cert_blob_combined.data() ) ); // do sign CRYPT_ALGORITHM_IDENTIFIER signature_alg={OID_G34311_DSTU4145_SIGN,0}; DWORD encoded_cert_size = 0; if( !CryptSignAndEncodeCertificate(cng_n_key_pair, 0, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, cert_to_be_signed, &signature_alg, 0, 0, &encoded_cert_size) ){ //TODO: this CryptSignAndEncodeCertificate leaks memory STCRYPT_UNEXPECTED(); } STCRYPT_CHECK(encoded_cert_size!=0); std::vector<BYTE> signed_certificate(encoded_cert_size); if( !CryptSignAndEncodeCertificate(cng_n_key_pair, 0, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, cert_to_be_signed, &signature_alg, 0, signed_certificate.data(), &encoded_cert_size) ){ STCRYPT_UNEXPECTED(); } signed_certificate.resize(encoded_cert_size); // context from signed blob ms_cert::pccert_context_t signed_cert_context( CertCreateCertificateContext (X509_ASN_ENCODING, reinterpret_cast<BYTE const*>( signed_certificate.data() ), signed_certificate.size() ) ); STCRYPT_CHECK( signed_cert_context ); // assign private key container name CRYPT_KEY_PROV_INFO key_prov_info = {0}; key_prov_info.pwszContainerName = const_cast<wchar_t*>( key_pair_container_name.c_str() ); key_prov_info.pwszProvName = CNG_STCRYPT_KEYSTORAGE; key_prov_info.dwProvType = 0; key_prov_info.dwFlags = 0; key_prov_info.cProvParam = 0; key_prov_info.rgProvParam = 0; key_prov_info.dwKeySpec = 0; STCRYPT_CHECK( CertSetCertificateContextProperty(signed_cert_context.handle(), CERT_KEY_PROV_INFO_PROP_ID, 0, &key_prov_info) ); STCRYPT_CHECK( CryptUIDlgViewContext (CERT_STORE_CERTIFICATE_CONTEXT, signed_cert_context.handle(), this->winId(), L"Generated CA certificate [NOT YET INSTALLED]", 0, 0) ); ms_cert::import_into_ms_store2(signed_cert_context.handle(), L"ROOT"); STCRYPT_CHECK( CryptUIDlgViewContext (CERT_STORE_CERTIFICATE_CONTEXT, signed_cert_context.handle(), this->winId(), L"Generated CA certificate", 0, 0) ); toy_ca::initialize_accept_requests_mode( dynamic_cast<QMainWindow*>( this->parent() ), std::move(signed_cert_context) ); GIE_QT_DEF_EXCEPTION_GUARD_END }
// Display a UI with the certificate info and also write it to the debug output HRESULT ShowCertInfo(PCCERT_CONTEXT pCertContext, CString Title) { TCHAR pszNameString[256]; void* pvData; DWORD cbData; DWORD dwPropId = 0; // Display the certificate. if (!CryptUIDlgViewContext( CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, NULL, CStringW(Title), 0, NULL)) { DebugMsg("UI failed."); } if (CertGetNameString( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, 128)) { DebugMsg("Certificate for %S", ATL::CT2W(pszNameString)); } else DebugMsg("CertGetName failed."); int Extensions = pCertContext->pCertInfo->cExtension; auto *p = pCertContext->pCertInfo->rgExtension; for (int i = 0; i < Extensions; i++) { DebugMsg("Extension %s", (p++)->pszObjId); } //------------------------------------------------------------------- // Loop to find all of the property identifiers for the specified // certificate. The loop continues until // CertEnumCertificateContextProperties returns zero. while (0 != (dwPropId = CertEnumCertificateContextProperties( pCertContext, // The context whose properties are to be listed. dwPropId))) // Number of the last property found. // This must be zero to find the first // property identifier. { //------------------------------------------------------------------- // When the loop is executed, a property identifier has been found. // Print the property number. DebugMsg("Property # %d found->", dwPropId); //------------------------------------------------------------------- // Indicate the kind of property found. switch (dwPropId) { case CERT_FRIENDLY_NAME_PROP_ID: { DebugMsg("Friendly name: "); break; } case CERT_SIGNATURE_HASH_PROP_ID: { DebugMsg("Signature hash identifier "); break; } case CERT_KEY_PROV_HANDLE_PROP_ID: { DebugMsg("KEY PROVE HANDLE"); break; } case CERT_KEY_PROV_INFO_PROP_ID: { DebugMsg("KEY PROV INFO PROP ID "); break; } case CERT_SHA1_HASH_PROP_ID: { DebugMsg("SHA1 HASH identifier"); break; } case CERT_MD5_HASH_PROP_ID: { DebugMsg("md5 hash identifier "); break; } case CERT_KEY_CONTEXT_PROP_ID: { DebugMsg("KEY CONTEXT PROP identifier"); break; } case CERT_KEY_SPEC_PROP_ID: { DebugMsg("KEY SPEC PROP identifier"); break; } case CERT_ENHKEY_USAGE_PROP_ID: { DebugMsg("ENHKEY USAGE PROP identifier"); break; } case CERT_NEXT_UPDATE_LOCATION_PROP_ID: { DebugMsg("NEXT UPDATE LOCATION PROP identifier"); break; } case CERT_PVK_FILE_PROP_ID: { DebugMsg("PVK FILE PROP identifier "); break; } case CERT_DESCRIPTION_PROP_ID: { DebugMsg("DESCRIPTION PROP identifier "); break; } case CERT_ACCESS_STATE_PROP_ID: { DebugMsg("ACCESS STATE PROP identifier "); break; } case CERT_SMART_CARD_DATA_PROP_ID: { DebugMsg("SMART_CARD DATA PROP identifier "); break; } case CERT_EFS_PROP_ID: { DebugMsg("EFS PROP identifier "); break; } case CERT_FORTEZZA_DATA_PROP_ID: { DebugMsg("FORTEZZA DATA PROP identifier "); break; } case CERT_ARCHIVED_PROP_ID: { DebugMsg("ARCHIVED PROP identifier "); break; } case CERT_KEY_IDENTIFIER_PROP_ID: { DebugMsg("KEY IDENTIFIER PROP identifier "); break; } case CERT_AUTO_ENROLL_PROP_ID: { DebugMsg("AUTO ENROLL identifier. "); break; } case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID: { DebugMsg("ISSUER PUBLIC KEY MD5 HASH identifier. "); break; } } // End switch. //------------------------------------------------------------------- // Retrieve information on the property by first getting the // property size. // For more information, see CertGetCertificateContextProperty. if (CertGetCertificateContextProperty( pCertContext, dwPropId, NULL, &cbData)) { // Continue. } else { // If the first call to the function failed, // exit to an error routine. DebugMsg("Call #1 to GetCertContextProperty failed."); return E_FAIL; } //------------------------------------------------------------------- // The call succeeded. Use the size to allocate memory // for the property. if (NULL != (pvData = (void*)malloc(cbData))) { // Memory is allocated. Continue. } else { // If memory allocation failed, exit to an error routine. DebugMsg("Memory allocation failed."); return E_FAIL; } //---------------------------------------------------------------- // Allocation succeeded. Retrieve the property data. if (CertGetCertificateContextProperty( pCertContext, dwPropId, pvData, &cbData)) { // The data has been retrieved. Continue. } else { // If an error occurred in the second call, // exit to an error routine. DebugMsg("Call #2 failed."); return E_FAIL; } //--------------------------------------------------------------- // Show the results. DebugMsg("The Property Content is"); PrintHexDump(cbData, pvData); //---------------------------------------------------------------- // Free the certificate context property memory. free(pvData); } return S_OK; }