//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1995 - 1996 // // File: tstore.cpp // // Contents: Cert Store API Tests // // See Usage() for list of test options. // // // Functions: main // // History: 04-Mar-96 philh created // 07-Jun-96 HelleS Added printing the command line // 20-Aug-96 jeffspel name changes // //-------------------------------------------------------------------------- #include #include #include "wincrypt.h" #include "certtest.h" #include "crypthlp.h" #include #include #include #include #include // // FIsWinNT: check OS type on x86. On non-x86, assume WinNT // #ifdef _M_IX86 static BOOL WINAPI FIsWinNT(void) { static BOOL fIKnow = FALSE; static BOOL fIsWinNT = FALSE; OSVERSIONINFO osVer; if(fIKnow) return(fIsWinNT); memset(&osVer, 0, sizeof(OSVERSIONINFO)); osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if( GetVersionEx(&osVer) ) fIsWinNT = (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT); // even on an error, this is as good as it gets fIKnow = TRUE; return(fIsWinNT); } #else static BOOL WINAPI FIsWinNT(void) { return(TRUE); } #endif static void PrintExpectedError(LPCSTR pszMsg) { DWORD dwErr = GetLastError(); printf("%s got expected error => 0x%x (%d) \n", pszMsg, dwErr, dwErr); } void PrintNoError(LPCSTR pszMsg) { printf("%s failed => expected error\n", pszMsg); } static BOOL AddCert(HCERTSTORE hStore, LPSTR pszAddFilename, DWORD dwAddDisposition, BOOL fExpectError) { BYTE *pbEncoded; DWORD cbEncoded; BOOL fResult; PCCERT_CONTEXT pCert = NULL; if (!ReadDERFromFile(pszAddFilename, &pbEncoded, &cbEncoded)) { PrintLastError("AddCert"); return FALSE; } fResult = FALSE; if (!CertAddEncodedCertificateToStore(hStore, dwCertEncodingType, pbEncoded, cbEncoded, dwAddDisposition, &pCert)) { if (fExpectError) PrintExpectedError("CertAddEncodedCertificateToStore"); else PrintLastError("CertAddEncodedCertificateToStore"); } else { if (fExpectError) PrintNoError("CertAddEncodedCertificateToStore"); else fResult = TRUE; printf("===== Added Cert =====\n"); DisplayCert(pCert, 0, 0); CertFreeCertificateContext(pCert); } TestFree(pbEncoded); return fResult; } static BOOL ReadCert( HCERTSTORE hStore, LPSTR pszReadFilename, DWORD dwDisplayFlags) { BOOL fResult; BYTE *pbEncoded; DWORD cbEncoded; PCCERT_CONTEXT pCert; if (!ReadDERFromFile(pszReadFilename, &pbEncoded, &cbEncoded)) { PrintLastError("ReadCert"); return FALSE; } pCert = CertCreateCertificateContext( dwCertEncodingType, pbEncoded, cbEncoded ); if (pCert == NULL) { fResult = FALSE; PrintLastError("CertCreateCertificateContext"); } else { fResult = TRUE; DisplayCert2(hStore, pCert, dwDisplayFlags); CertFreeCertificateContext(pCert); } TestFree(pbEncoded); return fResult; } // Attempt to read as a file containing an embedded PKCS#7 via SIP static HCERTSTORE OpenSIPStoreFile( LPSTR pszStoreFilename) { HCERTSTORE hStore = NULL; LPWSTR pwszStoreFilename = NULL; CRYPT_DATA_BLOB SignedData; memset(&SignedData, 0, sizeof(SignedData)); DWORD dwGetEncodingType; GUID gSubject; SIP_DISPATCH_INFO SipDispatch; SIP_SUBJECTINFO SubjectInfo; if (NULL == (pwszStoreFilename = AllocAndSzToWsz(pszStoreFilename))) goto CommonReturn; if (!CryptSIPRetrieveSubjectGuid( pwszStoreFilename, NULL, // hFile &gSubject)) goto CommonReturn; memset(&SipDispatch, 0, sizeof(SipDispatch)); SipDispatch.cbSize = sizeof(SipDispatch); if (!CryptSIPLoad( &gSubject, 0, // dwFlags &SipDispatch)) goto CommonReturn; memset(&SubjectInfo, 0, sizeof(SubjectInfo)); SubjectInfo.cbSize = sizeof(SubjectInfo); SubjectInfo.pgSubjectType = (GUID*) &gSubject; SubjectInfo.hFile = INVALID_HANDLE_VALUE; SubjectInfo.pwsFileName = pwszStoreFilename; // SubjectInfo.pwsDisplayName = // SubjectInfo.lpSIPInfo = // SubjectInfo.dwReserved = // SubjectInfo.hProv = // SubjectInfo.DigestAlgorithm = // SubjectInfo.dwFlags = SubjectInfo.dwEncodingType = dwMsgAndCertEncodingType; // SubjectInfo.lpAddInfo = if (!SipDispatch.pfGet( &SubjectInfo, &dwGetEncodingType, 0, // dwIndex &SignedData.cbData, NULL // pbSignedData ) || 0 == SignedData.cbData) goto CommonReturn; if (NULL == (SignedData.pbData = (BYTE *) TestAlloc(SignedData.cbData))) goto CommonReturn; if (!SipDispatch.pfGet( &SubjectInfo, &dwGetEncodingType, 0, // dwIndex &SignedData.cbData, SignedData.pbData )) goto CommonReturn; hStore = CertOpenStore( CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType, 0, // hCryptProv 0, // dwFlags (const void *) &SignedData ); if (hStore) { WCHAR wszGUID[128]; StringFromGUID2(gSubject, wszGUID, 128); printf("Opening Store as SIP Subject GUID:: %S \n", wszGUID); } CommonReturn: TestFree(pwszStoreFilename); TestFree(SignedData.pbData); return hStore; } static HCERTSTORE OpenCertStoreFile( LPSTR pszStoreFilename) { HCERTSTORE hStore; if (hStore = OpenSIPStoreFile(pszStoreFilename)) return hStore; return NULL; } static BOOL AddCrl(HCERTSTORE hStore, LPSTR pszAddFilename, DWORD dwAddDisposition, BOOL fExpectError) { BYTE *pbEncoded; DWORD cbEncoded; BOOL fResult; PCCRL_CONTEXT pCrl = NULL; if (!ReadDERFromFile(pszAddFilename, &pbEncoded, &cbEncoded)) { PrintLastError("AddCrl"); return FALSE; } fResult = FALSE; if (!CertAddEncodedCRLToStore(hStore, dwCertEncodingType, pbEncoded, cbEncoded, dwAddDisposition, &pCrl)) { if (fExpectError) PrintExpectedError("CertAddEncodedCRLToStore"); else PrintLastError("CertAddEncodedCRLToStore"); } else { if (fExpectError) PrintNoError("CertAddEncodedCRLToStore"); else fResult = TRUE; printf("===== Added CRL =====\n"); DisplayCrl(pCrl, 0); CertFreeCRLContext(pCrl); } TestFree(pbEncoded); return fResult; } static BOOL ReadCrl( LPSTR pszReadFilename, DWORD dwDisplayFlags) { BOOL fResult; BYTE *pbEncoded; DWORD cbEncoded; PCCRL_CONTEXT pCrl; if (!ReadDERFromFile(pszReadFilename, &pbEncoded, &cbEncoded)) { PrintLastError("ReadCrl"); return FALSE; } pCrl = CertCreateCRLContext( dwCertEncodingType, pbEncoded, cbEncoded ); if (pCrl == NULL) { fResult = FALSE; PrintLastError("CertCreateCRLContext"); } else { fResult = TRUE; DisplayCrl(pCrl, dwDisplayFlags); CertFreeCRLContext(pCrl); } TestFree(pbEncoded); return fResult; } // Attempt to read as a file containing an encoded CRL. static HCERTSTORE OpenCrlStoreFile( LPSTR pszStoreFilename) { HCERTSTORE hStore; BYTE *pbEncoded; DWORD cbEncoded; if (!ReadDERFromFile(pszStoreFilename, &pbEncoded, &cbEncoded)) return NULL; if (NULL == (hStore = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, // dwEncodingType 0, // hCryptProv 0, // dwFlags NULL // pvPara ))) return NULL; if (!CertAddEncodedCRLToStore( hStore, dwCertEncodingType, pbEncoded, cbEncoded, CERT_STORE_ADD_ALWAYS, NULL // ppCrlContext )) { CertCloseStore(hStore, 0); hStore = NULL; } TestFree(pbEncoded); return hStore; } static BOOL AddRootCtl( HCERTSTORE hStore, PCCTL_CONTEXT pCtl, DWORD dwAddDisposition, BOOL fExpectError ) { BOOL fResult; DWORD i; DWORD cCtlEntry = pCtl->pCtlInfo->cCTLEntry; PCTL_ENTRY pCtlEntry = pCtl->pCtlInfo->rgCTLEntry; HCERTSTORE hMsgStore = NULL; hMsgStore = CertOpenStore( CERT_STORE_PROV_MSG, dwMsgAndCertEncodingType, 0, // hCryptProv 0, // dwFlags (const void *) pCtl->hCryptMsg ); if (NULL == hMsgStore) { PrintLastError("Open Msg Store"); goto ErrorReturn; } // Loop through entries. Either add or remove the certificate from the // store for (i = 0; i< cCtlEntry; i++, pCtlEntry++) { PCRYPT_ATTRIBUTE pDelAttr; pDelAttr = CertFindAttribute( szOID_REMOVE_CERTIFICATE, pCtlEntry->cAttribute, pCtlEntry->rgAttribute ); if (pDelAttr) { BYTE rgbDelValue[] = {0x02, 0x1, 0x1}; if (0 == pDelAttr->cValue || 3 != pDelAttr->rgValue[0].cbData || 0 != memcmp(pDelAttr->rgValue[0].pbData, rgbDelValue, 3)) printf("Failed ==> bad delete attribute for Cert[%d]\n", i); else { PCCERT_CONTEXT pDelCert; pDelCert = CertFindCertificateInStore( hStore, 0, // dwCertEncodingType 0, // dwFindFlags CERT_FIND_SHA1_HASH, (const void *) &pCtlEntry->SubjectIdentifier, NULL //pPrevCertContext ); if (pDelCert) { if (CertDeleteCertificateFromStore(pDelCert)) printf("===== Deleted Root Cert[%d] =====\n", i); else printf("Failed ==> delete Cert[%d]\n", i); } } } else { PCCERT_CONTEXT pAddCert; pAddCert = CertFindCertificateInStore( hMsgStore, 0, // dwCertEncodingType 0, // dwFindFlags CERT_FIND_SHA1_HASH, (const void *) &pCtlEntry->SubjectIdentifier, NULL //pPrevCertContext ); if (pAddCert) { if (!CertSetCertificateContextPropertiesFromCTLEntry( pAddCert, pCtlEntry, CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG )) printf("Failed ==> SetPropFromCTLEntry for Cert [%d]\n", i); else { if (!CertAddCertificateContextToStore( hStore, pAddCert, dwAddDisposition, NULL // ppStoreContext )) printf("Failed ==> Add Cert [%d]\n", i); else printf("===== Added Root Cert[%d] =====\n", i); } CertFreeCertificateContext(pAddCert); } else printf("Failed ==> No Cert [%d]\n", i); } } fResult = TRUE; CommonReturn: if (hMsgStore) CertCloseStore(hMsgStore, 0); return fResult; ErrorReturn: fResult = FALSE; goto CommonReturn; } static BOOL AddCtl(HCERTSTORE hStore, LPSTR pszAddFilename, DWORD dwAddDisposition, BOOL fExpectError) { BYTE *pbEncoded; DWORD cbEncoded; BOOL fResult; PCCTL_CONTEXT pCtl = NULL; if (!ReadDERFromFile(pszAddFilename, &pbEncoded, &cbEncoded)) { PrintLastError("AddCtl"); return FALSE; } // Determine if Root CTL pCtl = CertCreateCTLContext( dwMsgAndCertEncodingType, pbEncoded, cbEncoded ); if (pCtl) { PCTL_USAGE pSubjectUsage = &pCtl->pCtlInfo->SubjectUsage; if (0 == pSubjectUsage->cUsageIdentifier || 0 != strcmp(pSubjectUsage->rgpszUsageIdentifier[0], szOID_ROOT_LIST_SIGNER)) { CertFreeCTLContext(pCtl); pCtl = NULL; } } fResult = FALSE; if (pCtl) { fResult = AddRootCtl( hStore, pCtl, dwAddDisposition, fExpectError ); CertFreeCTLContext(pCtl); } else if (!CertAddEncodedCTLToStore(hStore, dwMsgAndCertEncodingType, pbEncoded, cbEncoded, dwAddDisposition, &pCtl)) { if (fExpectError) PrintExpectedError("CertAddEncodedCTLToStore"); else PrintLastError("CertAddEncodedCTLToStore"); } else { if (fExpectError) PrintNoError("CertAddEncodedCTLToStore"); else fResult = TRUE; printf("===== Added CTL =====\n"); DisplayCtl(pCtl, 0, hStore); CertFreeCTLContext(pCtl); } TestFree(pbEncoded); return fResult; } static BOOL ReadCtl( LPSTR pszReadFilename, DWORD dwDisplayFlags) { BOOL fResult; BYTE *pbEncoded; DWORD cbEncoded; PCCTL_CONTEXT pCtl; if (!ReadDERFromFile(pszReadFilename, &pbEncoded, &cbEncoded)) { PrintLastError("ReadCtl"); return FALSE; } pCtl = CertCreateCTLContext( dwMsgAndCertEncodingType, pbEncoded, cbEncoded ); if (pCtl == NULL) { fResult = FALSE; PrintLastError("CertCreateCTLContext"); } else { fResult = TRUE; DisplayCtl(pCtl, dwDisplayFlags, NULL); CertFreeCTLContext(pCtl); } TestFree(pbEncoded); return fResult; } // Attempt to read as a file containing an encoded CTL. static HCERTSTORE OpenCtlStoreFile( LPSTR pszStoreFilename) { HCERTSTORE hStore; BYTE *pbEncoded; DWORD cbEncoded; if (!ReadDERFromFile(pszStoreFilename, &pbEncoded, &cbEncoded)) return NULL; if (NULL == (hStore = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, // dwEncodingType 0, // hCryptProv 0, // dwFlags NULL // pvPara ))) goto CommonReturn; if (!CertAddEncodedCTLToStore( hStore, dwMsgAndCertEncodingType, pbEncoded, cbEncoded, CERT_STORE_ADD_ALWAYS, NULL // ppCtlContext )) { CertCloseStore(hStore, 0); hStore = NULL; } CommonReturn: TestFree(pbEncoded); return hStore; } static PCCERT_CONTEXT GetNthCert( IN HCERTSTORE hStore, IN DWORD N ) { PCCERT_CONTEXT pCert = NULL; while (pCert = CertEnumCertificatesInStore(hStore, pCert)) { if (0 == N--) break; } return pCert; } static void SetKeyProvParams( IN PCCERT_CONTEXT pCert ) { CRYPT_KEY_PROV_INFO Info; CRYPT_KEY_PROV_PARAM Param[3]; DWORD i; BYTE rgb[11*3]; Info.pwszContainerName = L"Test Container With Parameters"; Info.pwszProvName = L"test provider with parameters"; Info.dwProvType = 77; Info.dwFlags = 0x12345678; Info.cProvParam = 3; Info.rgProvParam = Param; Info.dwKeySpec = 66; for (i = 0; i < sizeof(rgb); i++) rgb[i] = (BYTE) i; for (i = 0; i < 3; i++) { Param[i].dwParam = 0x10 + i; if (i == 0) Param[i].pbData = NULL; else Param[i].pbData = rgb; Param[i].cbData = i * 11; Param[i].dwFlags = 1 << i; } if (!CertSetCertificateContextProperty( pCert, CERT_KEY_PROV_INFO_PROP_ID, 0, // dwFlags &Info )) PrintLastError("CertSetCertificateContextProperty(KeyProvParams)"); } static void Usage(void) { printf("Usage: tstore [options] \n"); printf("Options are:\n"); printf(" -h - This message\n"); printf(" -b - Brief\n"); printf(" -c - Verify ALL checks enabled\n"); printf(" -cSign - Verify Signature check enabled\n"); printf(" -cTime - Verify Time Validity check enabled\n"); printf(" -d - Delete cert/CRL/CTL\n"); printf(" -dALL - Delete all certs/CRLs/CTLs\n"); printf(" -P - Set or Delete property\n"); printf(" -PKey - Find or Delete KeyProvInfo property\n"); printf(" -PSilentKey - Silent Find or Delete KeyProvInfo property\n"); printf(" -PArchive - Find or Delete Archive property\n"); printf(" -PKeyProvParam - Set KeyProvInfo with parameters\n"); printf(" -F - Test Force store close\n"); printf(" -e - Cert encoding type\n"); printf(" -f - Open dwFlags\n"); printf(" -E - Error is expected for add, delete or set\n"); printf(" -i - Cert/CRL/CTL index\n"); printf(" -l - List (Default)\n"); printf(" -R - Revocation (CRL)\n"); printf(" -T - Trust (CTL)\n"); printf(" -N - Enable change Notify\n"); printf(" -C - Commit before close\n"); printf(" -CForce - Force Commit before close\n"); printf(" -CClear - Clear Commit before close\n"); printf(" -s - Open the \"StoreName\" System store\n"); printf(" -s - Open using store provider\n"); printf(" -v - Verbose\n"); printf(" -u - UI Dialog Viewer\n"); printf(" -a - Add encoded cert/CRL/CTL from file\n"); printf(" -A - Add (replace) encoded cert/CRL/CTL from file\n"); printf(" -I - Add (inherit properties) encoded cert/CRL/CTL from file\n"); printf(" -p - Put encoded cert/CRL/CTL to file\n"); printf(" -r - Read encoded cert/CRL/CTL from file\n"); printf(" -t - Save thumprints (digests/hashes) in store\n"); printf(" -K - Display Public Key Thumbprint\n"); printf(" -S[] - Save store to file\n"); printf(" -7[] - PKCS# 7 formated save\n"); printf("\n"); printf("Default: list of certs for the store\n"); } int _cdecl main(int argc, char * argv[]) { DWORD dwDisplayFlags = 0; LONG lIndex = -1; BOOL fDelete = FALSE; BOOL fDeleteAll = FALSE; DWORD dwOpenFlags = 0; BOOL fExpectError = FALSE; BOOL fProperty = FALSE; BOOL fKeyProperty = FALSE; BOOL fKeyProvParam = FALSE; BOOL fSilentKey = FALSE; BOOL fArchiveProperty = FALSE; DWORD dwContextType = CERT_STORE_CERTIFICATE_CONTEXT; BOOL fThumbprint = FALSE; BOOL fSystemStore = FALSE; BOOL fForceClose = FALSE; BOOL fSave = FALSE; BOOL fPKCS7Save = FALSE; DWORD dwAddDisposition = CERT_STORE_ADD_USE_EXISTING; LPSTR pszAddFilename = NULL; LPSTR pszPutFilename = NULL; LPSTR pszReadFilename = NULL; LPSTR pszStoreFilename = NULL; LPSTR pszSaveFilename = NULL; LPSTR pszStoreProvider = NULL; HCERTSTORE hStore; BOOL fNotify = FALSE; HANDLE hEvent = NULL; BOOL fCommit = FALSE; DWORD dwCommitFlags = 0; BOOL fDeferClose = FALSE; #define DEFER_CERT_CNT 5 PCCERT_CONTEXT rgpDeferCert[DEFER_CERT_CNT]; memset(rgpDeferCert, 0, sizeof(rgpDeferCert)); while (--argc>0) { if (**++argv == '-') { switch(argv[0][1]) { case 'c': dwDisplayFlags |= DISPLAY_CHECK_FLAG; if (argv[0][2]) { if (0 == _stricmp(argv[0]+2, "Sign")) dwDisplayFlags |= DISPLAY_CHECK_SIGN_FLAG; else if (0 == _stricmp(argv[0]+2, "Time")) dwDisplayFlags |= DISPLAY_CHECK_TIME_FLAG; else { printf("Need to specify -cSign | -cTime\n"); Usage(); return -1; } } break; case 'b': dwDisplayFlags |= DISPLAY_BRIEF_FLAG; break; case 'v': dwDisplayFlags |= DISPLAY_VERBOSE_FLAG; break; case 'u': dwDisplayFlags |= DISPLAY_UI_FLAG; break; case 'K': dwDisplayFlags |= DISPLAY_KEY_THUMB_FLAG; break; case 'd': if (argv[0][2]) { if (0 != _stricmp(argv[0]+2, "ALL")) { printf("Need to specify -dALL\n"); Usage(); return -1; } fDeleteAll = TRUE; } else fDelete = TRUE; break; case 'P': if (argv[0][2]) { if (0 == _stricmp(argv[0]+2, "Key")) fKeyProperty = TRUE; else if (0 == _stricmp(argv[0]+2, "Archive")) fArchiveProperty = TRUE; else if (0 == _stricmp(argv[0]+2, "KeyProvParam")) fKeyProvParam = TRUE; else if (0 == _stricmp(argv[0]+2, "SilentKey")) { fKeyProperty = TRUE; fSilentKey = TRUE; } else { printf("Need to specify -PKey\n"); Usage(); return -1; } } else fProperty = TRUE; break; case 'F': fForceClose = TRUE; break; case 'R': dwContextType = CERT_STORE_CRL_CONTEXT; break; case 'T': dwContextType = CERT_STORE_CTL_CONTEXT; break; case 'N': fNotify = TRUE; break; case 'C': if (argv[0][2]) { if (0 == _stricmp(argv[0]+2, "Force")) dwCommitFlags |= CERT_STORE_CTRL_COMMIT_FORCE_FLAG; else if (0 == _stricmp(argv[0]+2, "Clear")) dwCommitFlags |= CERT_STORE_CTRL_COMMIT_CLEAR_FLAG; else { printf("Need to specify -CForce or -CClear\n"); Usage(); return -1; } } fCommit = TRUE; break; case 's': if (argv[0][2]) pszStoreProvider = argv[0]+2; fSystemStore = TRUE; break; case 't': fThumbprint = TRUE; break; case 'l': break; case 'e': dwCertEncodingType = (DWORD) strtoul(argv[0]+2, NULL, 0); break; case 'f': dwOpenFlags = (DWORD) strtoul(argv[0]+2, NULL, 0); break; case 'E': fExpectError = TRUE; break; case 'i': lIndex = (DWORD) strtol(argv[0]+2, NULL, 0); break; case 'a': case 'A': case 'I': pszAddFilename = argv[0]+2; if (*pszAddFilename == '\0') { printf("Need to specify filename\n"); Usage(); return -1; } if (argv[0][1] == 'A') dwAddDisposition = CERT_STORE_ADD_REPLACE_EXISTING; else if (argv[0][1] == 'I') dwAddDisposition = CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES; else dwAddDisposition = CERT_STORE_ADD_USE_EXISTING; break; case 'p': pszPutFilename = argv[0]+2; if (*pszPutFilename == '\0') { printf("Need to specify filename\n"); Usage(); return -1; } break; case 'r': pszReadFilename = argv[0]+2; if (*pszReadFilename == '\0') { printf("Need to specify filename\n"); Usage(); return -1; } break; case '7': fPKCS7Save = TRUE; case 'S': fSave = TRUE; if (argv[0][2]) pszSaveFilename = argv[0]+2; break; case 'h': default: Usage(); return -1; } } else pszStoreFilename = argv[0]; } if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) dwDisplayFlags &= ~DISPLAY_BRIEF_FLAG; if (pszStoreFilename == NULL) { printf("missing store filename\n"); Usage(); return -1; } if (pszSaveFilename == NULL) { if (!fSystemStore) pszSaveFilename = pszStoreFilename; else if (fSave) { printf("missing save filename\n"); Usage(); return -1; } } if (lIndex < 0 && (fDelete || pszPutFilename)) { printf("Must specify index value\n"); Usage(); return -1; } printf("command line: %s\n", GetCommandLine()); { DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */ DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */ if (I_CryptGetFileVersion(L"crypt32.dll", &dwFileVersionMS, &dwFileVersionLS)) printf("crypt32.dll file version:: %d.%d.%d.%d\n", (dwFileVersionMS >> 16) & 0xFFFF, dwFileVersionMS & 0xFFFF, (dwFileVersionLS >> 16) & 0xFFFF, dwFileVersionLS & 0xFFFF ); else PrintLastError("I_CryptGetFileVersion(crypt32.dll)"); } hStore = NULL; if (pszStoreProvider) { LPWSTR pwszStore; if (pwszStore = AllocAndSzToWsz(pszStoreFilename)) { hStore = CertOpenStore( pszStoreProvider, 0, // dwEncodingType 0, // hCryptProv dwOpenFlags, pwszStore ); TestFree(pwszStore); } if (hStore == NULL) { if (dwOpenFlags & CERT_STORE_DELETE_FLAG) { if (0 == GetLastError()) printf("Successful delete store\n"); else PrintLastError("CertOpenStore(CERT_STORE_DELETE_FLAG)"); return 0; } else { PrintLastError("CertOpenStore"); return -1; } } } else if (!fSystemStore) { // Attempt to open as encoded certificate CRL or CTL file switch (dwContextType) { case CERT_STORE_CRL_CONTEXT: hStore = OpenCrlStoreFile(pszStoreFilename); break; case CERT_STORE_CTL_CONTEXT: hStore = OpenCtlStoreFile(pszStoreFilename); break; case CERT_STORE_CERTIFICATE_CONTEXT: hStore = OpenCertStoreFile(pszStoreFilename); default: break; } } if (NULL == hStore) { // Attempt to open the store if (!fSystemStore && fCommit) { dwOpenFlags |= CERT_FILE_STORE_COMMIT_ENABLE_FLAG; pszSaveFilename = NULL; } dwOpenFlags |= CERT_STORE_SET_LOCALIZED_NAME_FLAG; hStore = OpenStoreEx(fSystemStore, pszStoreFilename, dwOpenFlags); if (hStore == NULL) return -1; } if (dwOpenFlags & CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG) { printf("CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG was set\n"); if (!fForceClose) fDeferClose = TRUE; } #if 0 if (fNotify && fSystemStore && !FIsWinNT()) { printf("Change Notify not supported for Win95 Registry\n"); fNotify = FALSE; } #endif if (fNotify) { // Create event to be notified if (NULL == (hEvent = CreateEvent( NULL, // lpsa FALSE, // fManualReset FALSE, // fInitialState NULL))) // lpszEventName PrintLastError("CreateEvent"); else { // Register the event to be signaled when the store changes if (!CertControlStore( hStore, 0, // dwFlags CERT_STORE_CTRL_NOTIFY_CHANGE, &hEvent )) { PrintLastError("CertControlStore(NOTIFY_CHANGE)"); fNotify = FALSE; } else Sleep(5); // Allow callback thread to be scheduled } } if (pszReadFilename) { printf("Reading\n"); switch (dwContextType) { case CERT_STORE_CRL_CONTEXT: ReadCrl(pszReadFilename, dwDisplayFlags); break; case CERT_STORE_CTL_CONTEXT: ReadCtl(pszReadFilename, dwDisplayFlags); break; default: ReadCert(hStore, pszReadFilename, dwDisplayFlags); } } else if (pszAddFilename) { BOOL fResult; printf("Adding\n"); switch (dwContextType) { case CERT_STORE_CRL_CONTEXT: fResult = AddCrl(hStore, pszAddFilename, dwAddDisposition, fExpectError); break; case CERT_STORE_CTL_CONTEXT: fResult = AddCtl(hStore, pszAddFilename, dwAddDisposition, fExpectError); break; default: fResult = AddCert(hStore, pszAddFilename, dwAddDisposition, fExpectError); } if (fResult) fSave = TRUE; } else if (fDeleteAll & !fArchiveProperty) { printf("Deleting All\n"); if (CERT_STORE_CRL_CONTEXT == dwContextType) { PCCRL_CONTEXT pCrl; while (pCrl = CertEnumCRLsInStore(hStore, NULL)) { if (!CertDeleteCRLFromStore(pCrl)) { if (fExpectError) PrintExpectedError("CertDeleteCRLFromStore"); else PrintLastError("CertDeleteCRLFromStore"); break; } else if (fExpectError) PrintNoError("CertDeleteCRLFromStore"); else fSave = TRUE; } } else if (CERT_STORE_CTL_CONTEXT == dwContextType) { PCCTL_CONTEXT pCtl; while (pCtl = CertEnumCTLsInStore(hStore, NULL)) { if (!CertDeleteCTLFromStore(pCtl)) { if (fExpectError) PrintExpectedError("CertDeleteCTLFromStore"); else PrintLastError("CertDeleteCTLFromStore"); break; } else if (fExpectError) PrintNoError("CertDeleteCTLFromStore"); else fSave = TRUE; } } else { PCCERT_CONTEXT pCert; while (pCert = CertEnumCertificatesInStore(hStore, NULL)) { if (!CertDeleteCertificateFromStore(pCert)) { if (fExpectError) PrintExpectedError("CertDeleteCertificateFromStore"); else PrintLastError("CertDeleteCertificateFromStore"); break; } else if (fExpectError) PrintNoError("CertDeleteCertificateFromStore"); else fSave = TRUE; } } } else if (CERT_STORE_CRL_CONTEXT == dwContextType) { BOOL fFound = FALSE; LONG i; PCCRL_CONTEXT pCrl = NULL; DWORD dwFlags; for (i = 0;; i++) { dwFlags = CERT_STORE_TIME_VALIDITY_FLAG; pCrl = CertGetCRLFromStore( hStore, NULL, // pIssuerContext pCrl, &dwFlags); if (pCrl == NULL) break; if ((lIndex >= 0) && (lIndex != i)) continue; fFound = TRUE; if (fProperty) { CRYPT_DATA_BLOB Data; BYTE rgbAux[] = {0xDE, 0xAD, 0xBE, 0xEF}; Data.pbData = rgbAux; Data.cbData = sizeof(rgbAux); if (!CertSetCRLContextProperty( pCrl, CERT_FIRST_USER_PROP_ID, 0, // dwFlags &Data )) { if (fExpectError) PrintExpectedError("CertSetCRLContextProperty"); else PrintLastError("CertSetCRLContextProperty"); } else if (fExpectError) PrintNoError("CertSetCRLContextProperty"); else fSave = TRUE; } if (fDelete) { printf("Deleting\n"); if (!CertDeleteCRLFromStore(pCrl)) { if (fExpectError) PrintExpectedError("CertDeleteCRLFromStore"); else PrintLastError("CertDeleteCRLFromStore"); } else if (fExpectError) PrintNoError("CertDeleteCRLFromStore"); else fSave = TRUE; break; } else if (pszPutFilename) { printf("Putting\n"); if (!WriteDERToFile( pszPutFilename, pCrl->pbCrlEncoded, pCrl->cbCrlEncoded )) PrintLastError("Put CRL::WriteDERToFile"); CertFreeCRLContext(pCrl); break; } else { if (fThumbprint) fSave = TRUE; printf("===== %d =====\n", i); DisplayCrl(pCrl, dwDisplayFlags); DisplayVerifyFlags("CRL", dwFlags); if (lIndex == i) { CertFreeCRLContext(pCrl); break; } } } if (!fFound) printf("CRL not found\n"); } else if (CERT_STORE_CTL_CONTEXT == dwContextType) { BOOL fFound = FALSE; LONG i; PCCTL_CONTEXT pCtl = NULL; for (i = 0;; i++) { pCtl = CertEnumCTLsInStore( hStore, pCtl); if (pCtl == NULL) break; if ((lIndex >= 0) && (lIndex != i)) continue; fFound = TRUE; if (fProperty) { CRYPT_DATA_BLOB Data; BYTE rgbAux[] = {0xDE, 0xAD, 0xBE, 0xEF}; Data.pbData = rgbAux; Data.cbData = sizeof(rgbAux); if (!CertSetCTLContextProperty( pCtl, CERT_FIRST_USER_PROP_ID, 0, // dwFlags &Data )) { if (fExpectError) PrintExpectedError("CertSetCTLContextProperty"); else PrintLastError("CertSetCTLContextProperty"); } else if (fExpectError) PrintNoError("CertSetCTLContextProperty"); else fSave = TRUE; } if (fDelete) { printf("Deleting\n"); if (!CertDeleteCTLFromStore(pCtl)) { if (fExpectError) PrintExpectedError("CertDeleteCTLFromStore"); else PrintLastError("CertDeleteCTLFromStore"); } else if (fExpectError) PrintNoError("CertDeleteCTLFromStore"); else fSave = TRUE; break; } else if (pszPutFilename) { printf("Putting\n"); if (!WriteDERToFile( pszPutFilename, pCtl->pbCtlEncoded, pCtl->cbCtlEncoded )) PrintLastError("Put CTL::WriteDERToFile"); CertFreeCTLContext(pCtl); break; } else { if (fThumbprint) fSave = TRUE; printf("===== %d =====\n", i); DisplayCtl(pCtl, dwDisplayFlags, hStore); if (lIndex == i) { CertFreeCTLContext(pCtl); break; } } } if (!fFound) printf("CTL not found\n"); } else { BOOL fFound = FALSE; LONG i; PCCERT_CONTEXT pCert = NULL; pCert = NULL; for (i = 0;; i++) { pCert = CertEnumCertificatesInStore( hStore, pCert); if (pCert == NULL) break; if ((lIndex >= 0) && (lIndex != i)) continue; fFound = TRUE; if (fForceClose) CertDuplicateCertificateContext(pCert); else if (fDeferClose) { CertFreeCertificateContext(rgpDeferCert[0]); rgpDeferCert[0] = CertDuplicateCertificateContext(pCert); } if (fProperty && !fDelete) { CRYPT_DATA_BLOB Data; BYTE rgbAux[] = {0xDE, 0xAD, 0xBE, 0xEF}; Data.pbData = rgbAux; Data.cbData = sizeof(rgbAux); if (!CertSetCertificateContextProperty( pCert, CERT_FIRST_USER_PROP_ID, 0, // dwFlags &Data )) { if (fExpectError) PrintExpectedError("CertSetCertificateContextProperty"); else PrintLastError("CertSetCertificateContextProperty"); } else if (fExpectError) PrintNoError("CertSetCertificateContextProperty"); else fSave = TRUE; // Test that we properly update the PROV_HANDLE and KEY_SPEC // properties HCRYPTPROV hProv = (HCRYPTPROV) 0x12345678; HCRYPTPROV hProv2 = 0; DWORD dwKeySpec = 0xdeadbeef; DWORD dwKeySpec2 = 0; if (!CertSetCertificateContextProperty( pCert, CERT_KEY_PROV_HANDLE_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG, (void *) hProv )) PrintLastError( "CertSetCertificateContextProperty(PROV_HANDLE)"); else if (!CertSetCertificateContextProperty( pCert, CERT_KEY_SPEC_PROP_ID, 0, // dwFlags &dwKeySpec )) PrintLastError( "CertSetCertificateContextProperty(KEY_SPEC)"); else { DWORD cbData = sizeof(hProv); CERT_KEY_CONTEXT KeyContext; if (!CertGetCertificateContextProperty( pCert, CERT_KEY_PROV_HANDLE_PROP_ID, &hProv2, &cbData)) PrintLastError( "CertGetCertificateContextProperty(PROV_HANDLE)"); else if (hProv2 != hProv) PrintLastError( "PROV_HANDLE property not updated properly\n"); cbData = sizeof(dwKeySpec); if (!CertGetCertificateContextProperty( pCert, CERT_KEY_SPEC_PROP_ID, &dwKeySpec2, &cbData)) PrintLastError( "CertGetCertificateContextProperty(KEY_SPEC)"); else if (dwKeySpec2 != dwKeySpec) PrintLastError( "KEY_SPEC property not updated properly\n"); cbData = sizeof(KeyContext); if (!CertGetCertificateContextProperty( pCert, CERT_KEY_CONTEXT_PROP_ID, &KeyContext, &cbData)) PrintLastError( "CertGetCertificateContextProperty(KEY_CONTEXT)"); else if (KeyContext.dwKeySpec != dwKeySpec || KeyContext.hCryptProv != hProv) PrintLastError( "KEY_CONTEXT property not updated properly\n"); } hProv = 0; if (!CertSetCertificateContextProperty( pCert, CERT_KEY_PROV_HANDLE_PROP_ID, 0, // dwFlags (void *) hProv )) PrintLastError( "CertSetCertificateContextProperty(PROV_HANDLE)"); } if (fKeyProperty && !fDelete) { if (!CryptFindCertificateKeyProvInfo( pCert, fSilentKey ? CRYPT_FIND_SILENT_KEYSET_FLAG : 0, NULL // pvReserved )) { if (fExpectError) PrintExpectedError("CryptFindCertificateKeyProvInfo"); else PrintLastError("CryptFindCertificateKeyProvInfo"); } else { printf("Found KEY_PROV_INFO property\n"); if (fExpectError) PrintNoError("CryptFindCertificateKeyProvInfo"); else { HCRYPTPROV hProv1 = 0; HCRYPTPROV hProv2 = 0; DWORD dwKeySpec1; DWORD dwKeySpec2; BOOL fCallerFreeProv; fSave = TRUE; dwKeySpec1 = 0x12341111; fCallerFreeProv = TRUE; if (!CryptAcquireCertificatePrivateKey( pCert, (fSilentKey ? CRYPT_ACQUIRE_SILENT_FLAG : 0) | CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, // pvReserved &hProv1, &dwKeySpec1, &fCallerFreeProv )) PrintLastError("CryptAcquireCertificatePrivateKey"); else if (fCallerFreeProv) printf("failed => cached acquire returned FreeProv\n"); dwKeySpec2 = 0x12342222; fCallerFreeProv = FALSE; if (!CryptAcquireCertificatePrivateKey( pCert, (fSilentKey ? CRYPT_ACQUIRE_SILENT_FLAG : 0) | CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, // pvReserved &hProv2, &dwKeySpec2, &fCallerFreeProv )) PrintLastError("CryptAcquireCertificatePrivateKey"); else { if (!fCallerFreeProv) printf("failed => uncached acquire didn't return FreeProv\n"); if (hProv2 == hProv1) printf("failed => uncached == cached hProv\n"); if (dwKeySpec2 != dwKeySpec1) printf("failed => uncached != cached dwKeySpec\n"); CryptReleaseContext(hProv2, 0); } if (hProv1) { dwKeySpec2 = 0x12343333; fCallerFreeProv = TRUE; if (!CryptAcquireCertificatePrivateKey( pCert, (fSilentKey ? CRYPT_ACQUIRE_SILENT_FLAG : 0) | CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, // pvReserved &hProv2, &dwKeySpec2, &fCallerFreeProv )) PrintLastError("CryptAcquireCertificatePrivateKey"); else { if (fCallerFreeProv) printf("failed => uncached acquire returned FreeProv\n"); if (hProv2 != hProv1) printf("failed => cached != cached hProv\n"); if (dwKeySpec2 != dwKeySpec1) printf("failed => cached != cached dwKeySpec\n"); } } } } } if (fArchiveProperty) { CRYPT_DATA_BLOB ArchiveBlob = { 0, NULL }; if (!CertSetCertificateContextProperty( pCert, CERT_ARCHIVED_PROP_ID, 0, // dwFlags (fDelete || fDeleteAll) ? NULL : &ArchiveBlob )) { if (fExpectError) PrintExpectedError( "CertSetCertificateContextProperty(ARCHIVE)"); else PrintLastError( "CertSetCertificateContextProperty(ARCHIVE)"); } } else if (fDelete) { if (fProperty || fKeyProperty) { DWORD PropId; if (fKeyProperty) { printf("Deleting KEY_PROV_INFO property\n"); PropId = CERT_KEY_PROV_INFO_PROP_ID; } else { printf("Deleting property\n"); PropId = CERT_FIRST_USER_PROP_ID; } if (!CertSetCertificateContextProperty( pCert, PropId, 0, // dwFlags NULL )) { if (fExpectError) PrintExpectedError("CertSetCertificateContextProperty"); else PrintLastError("CertSetCertificateContextProperty"); } else if (fExpectError) PrintNoError("CertSetCertificateContextProperty"); else fSave = TRUE; CertFreeCertificateContext(pCert); } else { printf("Deleting\n"); if (!CertDeleteCertificateFromStore(pCert)) { if (fExpectError) PrintExpectedError("CertDeleteCertificateFromStore"); else PrintLastError("CertDeleteCertificateFromStore"); } else if (fExpectError) PrintNoError("CertDeleteCertificateFromStore"); else fSave = TRUE; } break; } else if (pszPutFilename) { printf("Putting\n"); if (!WriteDERToFile( pszPutFilename, pCert->pbCertEncoded, pCert->cbCertEncoded )) PrintLastError("Put Cert::WriteDERToFile"); CertFreeCertificateContext(pCert); break; } else { if (fKeyProvParam) { printf("Setting KeyProvInfo parameters\n"); SetKeyProvParams(pCert); } if (fThumbprint) fSave = TRUE; printf("===== %d =====\n", i); DisplayCert(pCert, dwDisplayFlags); if (lIndex == i) { CertFreeCertificateContext(pCert); break; } } } if (!fFound) printf("Certificate not found\n"); if (fForceClose) { // Do incomplete enumerations to test out external store // logic pCert = GetNthCert(hStore, 0); CertFreeCertificateContext(pCert); pCert = GetNthCert(hStore, 0); GetNthCert(hStore, (i-1)/2); GetNthCert(hStore, i-1); } else if (fDeferClose) { rgpDeferCert[1] = GetNthCert(hStore, 0); CertFreeCertificateContext(rgpDeferCert[1]); rgpDeferCert[1] = GetNthCert(hStore, 0); rgpDeferCert[2] = GetNthCert(hStore, (i-1)/2); rgpDeferCert[3] = GetNthCert(hStore, i-1); } } if (fSave && pszSaveFilename) SaveStoreEx(hStore, fPKCS7Save, pszSaveFilename); if (fCommit) { printf("Committing store changes::"); if (dwCommitFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG) printf(" FORCE"); if (dwCommitFlags & CERT_STORE_CTRL_COMMIT_CLEAR_FLAG) printf(" CLEAR"); printf("\n"); if (!CertControlStore( hStore, dwCommitFlags, CERT_STORE_CTRL_COMMIT, NULL )) PrintLastError("CertControlStore(COMMIT)"); } if (fNotify) { BOOL fSignaled; // Check if event was signaled if (WAIT_TIMEOUT == WaitForSingleObjectEx( hEvent, 100, // dwMilliseconds FALSE // bAlertable )) fSignaled = FALSE; else fSignaled = TRUE; if (!fSignaled) { printf("No store change notify\n"); if (pszAddFilename || fDeleteAll || fDelete || fProperty) printf("failed => expected notify for add, delete or property\n"); } else { printf("There was a store change notify\n"); if (!(pszAddFilename || fDeleteAll || fDelete || fProperty)) printf("failed => unexpected notify\n"); if (!CertControlStore( hStore, 0, // dwFlags CERT_STORE_CTRL_RESYNC, NULL // pvCtrlPara )) PrintLastError("CertControlStore(RESYNC)"); else { printf("\n"); printf(">>>>> After Resync >>>>>\n"); DisplayStore(hStore, DISPLAY_BRIEF_FLAG); } } } if (hEvent) CloseHandle(hEvent); if (fForceClose) { CertDuplicateStore(hStore); if (CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG | CERT_CLOSE_STORE_FORCE_FLAG)) printf("failed => CertCloseStore(FORCE) didn't fail as expected\n"); else printf("CertCloseStore(FORCE) returned expected nonzero status: 0x%x\n", GetLastError()); } else if (fDeferClose) { // Check if any defered certificates DWORD i; fDeferClose = FALSE; for (i = 0; i < DEFER_CERT_CNT; i++) { if (rgpDeferCert[i]) { fDeferClose = TRUE; break; } } if (fDeferClose) { CertDuplicateStore(hStore); CertCloseStore(hStore, 0); if (CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG)) printf("failed => CertCloseStore(DEFER) didn't fail as expected\n"); else printf("CertCloseStore(DEFER) returned expected nonzero status: 0x%x\n", GetLastError()); for (i = 0; i < DEFER_CERT_CNT; i++) { CertFreeCertificateContext(rgpDeferCert[i]); } } else { if (!CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG)) PrintLastError("CertCloseStore(DEFER)"); } } else { if (!CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG)) PrintLastError("CertCloseStore"); } return 0; }