You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1636 lines
56 KiB
1636 lines
56 KiB
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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 <windows.h>
|
|
#include <assert.h>
|
|
#include "wincrypt.h"
|
|
#include "certtest.h"
|
|
#include "crypthlp.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
|
|
//
|
|
// 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] <StoreName>\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<number> - Cert encoding type\n");
|
|
printf(" -f<number> - Open dwFlags\n");
|
|
printf(" -E - Error is expected for add, delete or set\n");
|
|
printf(" -i<number> - 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<StoreProviderName> - Open using store provider\n");
|
|
printf(" -v - Verbose\n");
|
|
printf(" -u - UI Dialog Viewer\n");
|
|
printf(" -a<filename> - Add encoded cert/CRL/CTL from file\n");
|
|
printf(" -A<filename> - Add (replace) encoded cert/CRL/CTL from file\n");
|
|
printf(" -I<filename> - Add (inherit properties) encoded cert/CRL/CTL from file\n");
|
|
printf(" -p<filename> - Put encoded cert/CRL/CTL to file\n");
|
|
printf(" -r<filename> - 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[<SaveFilename>] - Save store to file\n");
|
|
printf(" -7[<SaveFilename>] - 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;
|
|
}
|